Cancelar Sector Primario
Esta sección detalla la operación para solicitar la cancelación de un CFDI emitido por un contribuyente del Sector Primario (SP).
Descripción de la Operación
Esta operación permite cancelar un CFDI de Sector Primario de forma simplificada. A diferencia de otros métodos de cancelación, este no requiere el envío de los Certificados de Sello Digital (CSD) del emisor. La autenticación se realiza a través del apikey.
Este método es exclusivo para los CFDI que fueron expedidos para el Sector Primario.
Parámetros de Entrada (Input)
| Parámetro | Tipo de Dato | Descripción |
|---|---|---|
apikey |
string |
Credencial de acceso al servicio (Solicita aquí). |
rfcEmisor |
string |
RFC del contribuyente emisor del CFDI (del Sector Primario). |
uuid |
string |
Folio Fiscal (UUID) del CFDI que se desea cancelar. |
Parámetros de Salida (Output) - RespuestaCancelar
La respuesta de esta operación es idéntica a la de la operación cancelar2.
| 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 |
Acuse de cancelación en formato XML, devuelto por el SAT. |
status |
string |
Indica el estado de la solicitud. Puede ser success (éxito) o error (fallido). |
Ejemplo de Código
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
using System;
using System.Threading.Tasks;
public class CancelarSPRequest
{
public string Apikey { get; set; }
public string RfcEmisor { get; set; }
public string Uuid { get; set; }
}
public async Task<RespuestaCancelar> CancelarSPAsync(CancelarSPRequest request)
{
using var client = new ServicioTimbradoWSPortTypeClient("ServicioTimbradoWSPort");
try
{
var response = await client.cancelarSPAsync(request.Apikey, request.RfcEmisor, request.Uuid);
return new RespuestaCancelar { Code = response.code, Message = response.message, Data = response.data, Status = response.status };
}
catch (Exception ex)
{
Console.WriteLine($"Error al cancelar CFDI de Sector Primario: {ex.Message}");
throw;
}
}
public class RespuestaCancelar
{
public string? Code { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
public string? Status { get; set; }
}
// Ejemplo de uso
public async Task EjemploUsoCancelarSPAsync()
{
var request = new CancelarSPRequest
{
Apikey = "TU_API_KEY_AQUI",
RfcEmisor = "ABC010101XYZ",
Uuid = "C3D4E08E-12F3-4B0C-8A4D-78E6B8E47113"
};
var resultado = await CancelarSPAsync(request);
if (resultado?.Status == "success")
{
Console.WriteLine("¡Cancelación de CFDI SP Exitosa!");
Console.WriteLine($"Mensaje: {resultado.Message}");
Console.WriteLine("Acuse:");
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 CancelarSPService {
// ... (Definición de ExecutorService, Logger, etc.)
public CompletableFuture<RespuestaCancelar> cancelarSPAsync(String apiKey, String rfcEmisor, String uuid) {
return CompletableFuture.supplyAsync(() -> {
try {
ServicioTimbradoWS service = new ServicioTimbradoWS();
ServicioTimbradoWSPortType port = service.getServicioTimbradoWSPort();
Respuesta response = port.cancelarSP(apiKey, rfcEmisor, uuid);
RespuestaCancelar resultado = new RespuestaCancelar();
resultado.setCode(response.getCode());
resultado.setMessage(response.getMessage());
resultado.setData(response.getData());
resultado.setStatus(response.getStatus());
return resultado;
} catch (Exception ex) {
throw new RuntimeException("Error al cancelar CFDI de Sector Primario", ex);
}
}, executor);
}
// Ejemplo de uso
public static void main(String[] args) {
CancelarSPService service = new CancelarSPService();
String apiKey = "TU_API_KEY_AQUI";
String rfcEmisor = "ABC010101XYZ";
String uuid = "C3D4E08E-12F3-4B0C-8A4D-78E6B8E47113";
service.cancelarSPAsync(apiKey, rfcEmisor, uuid)
.whenComplete((resultado, ex) -> {
if (ex != null) {
System.err.println("Error: " + ex.getMessage());
} else if ("success".equals(resultado.getStatus())) {
System.out.println("¡Cancelación de CFDI SP Exitosa!");
System.out.println("Acuse: " + 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
class CancelarSPService:
def __init__(self, wsdl_url: str):
self.wsdl_url = wsdl_url
self.async_client = AsyncClient(self.wsdl_url)
async def cancelar_sp_async(self, **kwargs) -> dict:
response = await self.async_client.service.cancelarSP(**kwargs)
return response
async def main():
service = CancelarSPService("https://dev.facturaloplus.com/ws/servicio.do?wsdl")
params = {
"apikey": "TU_API_KEY_AQUI",
"rfcEmisor": "ABC010101XYZ",
"uuid": "C3D4E08E-12F3-4B0C-8A4D-78E6B8E47113"
}
resultado = await service.cancelar_sp_async(**params)
if resultado and resultado['status'] == 'success':
print("¡Cancelación de CFDI SP Exitosa!")
print(f"Mensaje: {resultado['message']}")
print(f"Acuse: {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
class CancelarSPService {
private string $wsdlUrl;
public function __construct(string $wsdlUrl) {
$this->wsdlUrl = $wsdlUrl;
}
public function cancelarSP(array $params): ?object {
try {
$soapClient = new SoapClient($this->wsdlUrl, ['trace' => 1, 'exceptions' => true]);
$response = $soapClient->cancelarSP($params);
return $response->return ?? null;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
return null;
}
}
}
// Ejemplo de uso
$service = new CancelarSPService("https://dev.facturaloplus.com/ws/servicio.do?wsdl");
$params = [
'apikey' => "TU_API_KEY_AQUI",
'rfcEmisor' => "ABC010101XYZ",
'uuid' => "C3D4E08E-12F3-4B0C-8A4D-78E6B8E47113"
];
$resultado = $service->cancelarSP($params);
header('Content-Type: text/plain');
if ($resultado && $resultado->status === 'success') {
echo "¡Cancelación de CFDI SP Exitosa!\n";
echo "Mensaje: {$resultado->message}\n";
echo "Acuse: {$resultado->data}\n";
} else {
echo "Error: {$resultado->code} - {$resultado->message}\n";
}
?>
Respuesta (Response)
El campo data contendrá el acuse de cancelación del SAT.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope ...>
<SOAP-ENV:Body>
<ns1:cancelarSPResponse xmlns:ns1="urn:ws_api">
<return xsi:type="tns:RespuestaCancelar">
<code xsi:type="xsd:string">200</code>
<message xsi:type="xsd:string">Solicitud de cancelación recibida</message>
<data xsi:type="xsd:string"><![CDATA[<Acuse ... />]]></data>
<status xsi:type="xsd:string">success</status>
</return>
</ns1:cancelarSPResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>Códigos de respuesta
Los códigos de respuesta para la cancelación 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 cancelación a través de la API.
| Código | Descripción | Detalle |
|---|---|---|
| 200 | UUID Cancelado exitosamente | Se considera una solicitud de cancelación exitosa , sin embargo esto no asegura su cancelación |
| 202 | UUID Previamente cancelado | Se considera previamente cancelado. Estatus cancelado ante el SAT |
| 203 | UUID No corresponde el RFC del emisor y de quien solicita la cancelación | |
| 205 | No existe | El SAT da una prórroga de 72 hrs para que el comprobante aparezca con estatus Vigente posterior al envío por parte del proovedor de Certificación de CFDI. Puede que algunos comprobantes no aparezcan al momento, es necesario esperar por lo menos 72 hrs |
| CA 1000 | CA 1000 - El xml proporcionado está mal formado o es inválido | El comprobante no corresponde a la estructura de un XML o tiene mal la estructura |
| CA 2000 | CA 2000 - No fue posible cancelar el CFDI, en estos momentos existe una intermitencia en el servicio de cancelación del SAT, por favor inente más tarde, el error que regresa el SAT es: | Adicional al mensaje se agregara el mensaje generado por el servicio SAT |
| CA 2100 | CA 2100 - No fue posible cancelar el CFDI, por favor intentelo más tarde, si el problema persiste contacte a soporte técnico. | Hubo una intermitencia con el servicio del SAT y/o servicio, por favor intentelo más tarde. |
| CA 3000 | CA 2300 - No fue posible cancelar el CFDI, por favor intentelo más tarde, si el problema persiste contacte a soporte técnico | |
| CA203 | CA203 - El UUID tiene un fallo correspondiente al emisor | Acuse con error en Folio 203 |
| CA204 | CA204 - El SAT no ve que el UUID sea aplicable para cancelación | |
| CA205 | CA205 - El UUID no existe | Acuse con error en folio 205 |
| CA300 | CA300 - La autenticación es incorrecta | El comprobante está mal formado, verifique los esquemas del comprobante |
| CA301 | CA301 - El XML está mal formado o es incorrecto | El comprobante está mal formado, verifique los esquemas del comprobante |
| CA302 | CA302 - Sello mal formado o inválido | El sello no es válido o fue alterado |
| CA303 | CA303 - Sello no corresponde a emisor o caduco | El sello no fue generado con el certificado del emisor del comprobante |
| CA304 | CA304 - Certificado revocado o caduco | El certificado con el que se emitió el comprobante fue revocado o se encuentra caduco |
| CA305 | CA305 - La fecha de emisión no está dentro de la vigencia del CSD del Emisor | La fecha de emisión del comprobante no se encuentra dentro de la vigencia del certificado con cual fue sellado |
| CA306 | CA306 - El certificado no es de tipo CSD | Los comprobantes únicamente se pueden emitir y timbrar usando CSD |
| CA307 | CA307 - El CFDI contiene un timbre previo | El comprobante ya cuenta con un complemento TFD |
| CA308 | CA308 - Certificado no expedido por el SAT | El certificado que se utiliza para timbrar no fue generado por el SAT |
| CA309 | CA309 - No existe cancelación que corresponda con el ID proporcionado | |
| CASD | CASD - Acuse sin descripción específica | |
| CACFDI33 | CACFDI33 - Problemas con los campos | El error puede ser generado por varias opciones: Se está usando un Certificado FIEL en lugar de CSD, No se están enviando todos los campos necesarios. |
| 300 | API KEY Inválida o inexistente |