Cómo integrar Factura Electrónica ARCA (ex AFIP) WSFEv1 en Argentina: creá tu facturador sin programar con MIA (alojado en su propia VPS) o conectalo en PHP 8.4 y WooCommerce
Emitir Factura Electrónica A, B o C en tiempo real contra los WebServices de ARCA (ex AFIP) —con obtención automática de CAE, validación de Condición frente al IVA (RG 5616) y generación del Código QR oficial— suele ser uno de los mayores dolores de cabeza técnicos en Argentina. En esta guía vas a ver los dos caminos para resolverlo hoy: pedírselo en lenguaje natural a MIA (nuestra Inteligencia Artificial que lo programa, configura los certificados y te lo deja corriendo en su propia Cloud VPS dedicada) o implementarlo paso a paso en PHP 8.4 y WordPress.
¿No querés renegar con WebServices de ARCA/AFIP? Pedíselo a MIA y recibilo funcionando en tu propia VPS
Con MIA (Desarrollo con Inteligencia Artificial de MESI), no necesitás programar clientes SOAP ni configurar servidores Linux a mano. Le explicás en palabras simples qué necesita tu empresa y el ecosistema MIA + Antigravity Agent Manager + Soporte Técnico de MESI se encarga de todo:
1. Lo pedís en lenguaje natural
«Quiero un sistema de facturación conectado a ARCA y Mercado Pago que emita Factura A o B con QR en PDF y la mande por WhatsApp y correo al cliente».
2. MIA programa WSAA + WSFEv1
MIA genera la base de datos, el panel administrativo, la consulta de padrón de CUIT, el cálculo de IVA, el caché de tickets TA.xml y el PDF con QR oficial.
3. Queda hosteado en su propia VPS
Tu facturador o ERP queda desplegado y blindado en tu propia Cloud VPS dedicada, con certificado SSL, backups y soporte humano de MESI.
1 Cómo funciona la arquitectura de Facturación Electrónica de ARCA (ex AFIP)
A diferencia de las APIs REST modernas que usan un simple Bearer Token estático, la infraestructura de WebServices de ARCA (Agencia de Recaudación y Control Aduanero, ex AFIP) separa estrictamente la autenticación criptográfica de la autorización contable del comprobante en dos servicios SOAP distintos:
| WebService ARCA | Función Técnica | Endpoint Homologación (Testing) | Endpoint Producción |
|---|---|---|---|
| 1. WSAA (Autenticación y Autorización) |
Recibe un XML TRA firmado con tu clave privada X.509 (LoginCms) y devuelve un Ticket de Acceso (Token + Sign) válido por 12 horas. |
https://wsaahomo.afip.gov.ar/ws/services/LoginCms |
https://wsaa.afip.gov.ar/ws/services/LoginCms |
| 2. WSFEv1 (Factura Electrónica v1) |
Recibe el Token, el Sign y los datos del comprobante en FECAESolicitar y devuelve el CAE (Código de Autorización Electrónico) y su fecha de vencimiento. |
https://wswhomo.afip.gov.ar/wsfev1/service.asmx |
https://servicios1.afip.gov.ar/wsfev1/service.asmx |
LoginCms dura 12 horas. Si tu script solicita otro ticket mientras el anterior sigue activo, ARCA devuelve el error coe.alreadyAuthenticated: El CEE ya posee un TA valido para el acceso al WSN solicitado.
2 Generar la Clave Privada RSA 2048 y el Pedido CSR con OpenSSL
El primer paso técnico es generar tu par de claves criptográficas: una clave privada (afip_privada.key, que jamás sale de tu servidor) y una solicitud de certificado (afip_pedido.csr) que subirás al portal de ARCA con Clave Fiscal Nivel 3.
Ejecutá estos dos comandos en tu terminal SSH (reemplazando MiEmpresaSRL por tu razón social y 30123456789 por tu CUIT sin guiones):
# 1. Generar la clave privada RSA de 2048 bits (proteger con chmod 600) openssl genrsa -out afip_privada.key 2048 chmod 600 afip_privada.key # 2. Generar el Certificate Signing Request (CSR) con el formato exacto exigido por ARCA openssl req -new -key afip_privada.key \ -subj "/C=AR/O=MiEmpresaSRL/CN=facturador/serialNumber=CUIT 30123456789" \ -out afip_pedido.csr
Cómo dar de alta el certificado y el Punto de Venta en ARCA:
- Ingresá con Clave Fiscal al portal de ARCA (ex AFIP) y abrí el servicio «Administración de Certificados Digitales» (si primero vas a probar en testing, usá «WSASS - Autogestión Certificados Homologación»).
- Agregá un alias (computador fiscal), subí el archivo
afip_pedido.csry descargá el certificado firmadoafip_certificado.crt. - Entrá a «Administrador de Relaciones de Clave Fiscal» → «Nueva Relación», buscá dentro de ARCA → WebServices el servicio «Facturación Electrónica» (
wsfe) y en «Representante» seleccioná el Computador Fiscal que recién creaste. - Por último, en «Administración de Puntos de Venta y Domicilios» → «A/B/M de Puntos de Venta», creá un Punto de Venta exclusivo con el sistema «RECE para aplicativo y Web Services» (si sos Responsable Inscripto) o «Factura Electrónica - Monotributo - Web Services».
3 Código PHP 8.4 completo: caché de WSAA, emisión WSFEv1 (RG 5616) y Código QR oficial
Desde la entrada en vigencia de la Resolución General 5616 (RG 5616), ARCA rechaza cualquier llamada a FECAESolicitar que no incluya el campo CondicionIVAReceptorId (por ejemplo: 1 = IVA Responsable Inscripto, 5 = Consumidor Final, 6 = Responsable Monotributo, 4 = IVA Sujeto Exento).
Además, todo comprobante electrónico debe incluir el Código QR oficial (RG 4892) que codifica un JSON en Base64 apuntando a https://www.afip.gob.ar/fe/qr/?p=.... A continuación tenés una implementación limpia y lista para producción en PHP 8.4:
<?php
declare(strict_types=1);
final class ArcaFacturador
{
private string $cuit;
private string $certPath;
private string $keyPath;
private string $cacheDir;
private bool $production;
public function __construct(
string $cuit,
string $certPath,
string $keyPath,
string $cacheDir,
bool $production = true
) {
$this->cuit = preg_replace('/\D/', '', $cuit);
$this->certPath = $certPath;
$this->keyPath = $keyPath;
$this->cacheDir = rtrim($cacheDir, '/');
$this->production = $production;
}
/**
* Obtiene Token y Sign de WSAA reutilizando el caché local durante 12 horas
*/
public function obtenerTicketAcceso(string $service = 'wsfe'): array
{
$taFile = $this->cacheDir . '/ta_' . $service . '_' . ($this->production ? 'prod' : 'homo') . '.xml';
if (is_file($taFile)) {
$xml = @simplexml_load_file($taFile);
if ($xml && isset($xml->header->expirationTime)) {
$exp = strtotime((string)$xml->header->expirationTime);
if ($exp > (time() + 600)) {
return [
'token' => (string)$xml->credentials->token,
'sign' => (string)$xml->credentials->sign,
];
}
}
}
// Generar TRA (Ticket de Requerimiento de Acceso)
$traFile = $this->cacheDir . '/tra_' . bin2hex(random_bytes(6)) . '.xml';
$cmsFile = $traFile . '.cms';
$now = time();
$traXml = '<?xml version="1.0" encoding="UTF-8"?>'
. '<loginTicketRequest version="1.0">'
. '<header>'
. '<uniqueId>' . $now . '</uniqueId>'
. '<generationTime>' . gmdate('c', $now - 600) . '</generationTime>'
. '<expirationTime>' . gmdate('c', $now + 600) . '</expirationTime>'
. '</header>'
. '<service>' . htmlspecialchars($service, ENT_XML1) . '</service>'
. '</loginTicketRequest>';
file_put_contents($traFile, $traXml, LOCK_EX);
$signed = openssl_pkcs7_sign(
$traFile,
$cmsFile,
'file://' . $this->certPath,
['file://' . $this->keyPath, ''],
[],
PKCS7_BINARY | PKCS7_NOATTR
);
@unlink($traFile);
if (!$signed) {
throw new RuntimeException('Error al firmar TRA con OpenSSL: ' . openssl_error_string());
}
$cmsRaw = file_get_contents($cmsFile);
@unlink($cmsFile);
$parts = preg_split("/\r?\n\r?\n/", $cmsRaw, 2);
$cmsClean = trim($parts[1] ?? '');
$wsaaWsdl = $this->production
? 'https://wsaa.afip.gov.ar/ws/services/LoginCms?WSDL'
: 'https://wsaahomo.afip.gov.ar/ws/services/LoginCms?WSDL';
$client = new SoapClient($wsaaWsdl, [
'soap_version' => SOAP_1_2,
'exceptions' => true,
'trace' => false,
'cache_wsdl' => WSDL_CACHE_DISK,
]);
$response = $client->loginCms(['in0' => $cmsClean]);
$taXmlStr = (string)$response->loginCmsReturn;
file_put_contents($taFile, $taXmlStr, LOCK_EX);
@chmod($taFile, 0600);
$xml = simplexml_load_string($taXmlStr);
return [
'token' => (string)$xml->credentials->token,
'sign' => (string)$xml->credentials->sign,
];
}
/**
* Autoriza una Factura Electrónica en WSFEv1 (incluye CondicionIVAReceptorId RG 5616)
* $cbteTipo: 1 = Factura A | 6 = Factura B | 11 = Factura C
* $condicionIvaReceptor: 1 = Resp. Inscripto | 5 = Consumidor Final | 6 = Monotributo | 4 = Exento
*/
public function autorizarComprobante(
int $ptoVta,
int $cbteTipo,
int $docTipo,
int $docNro,
int $condicionIvaReceptor,
float $impNeto,
float $impIva
): array {
$ta = $this->obtenerTicketAcceso('wsfe');
$wsfeWsdl = $this->production
? 'https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL'
: 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL';
$client = new SoapClient($wsfeWsdl, [
'soap_version' => SOAP_1_2,
'exceptions' => true,
'cache_wsdl' => WSDL_CACHE_DISK,
]);
$auth = [
'Token' => $ta['token'],
'Sign' => $ta['sign'],
'Cuit' => (float)$this->cuit,
];
// 1. Consultar último número de comprobante autorizado
$ult = $client->FECompUltimoAutorizado([
'Auth' => $auth,
'PtoVta' => $ptoVta,
'CbteTipo' => $cbteTipo,
]);
$proximoNro = (int)$ult->FECompUltimoAutorizadoResult->CbteNro + 1;
$impTotal = round($impNeto + $impIva, 2);
$fechaHoy = date('Ymd');
// 2. Solicitar CAE en FECAESolicitar
$det = [
'Concepto' => 1, // 1 = Productos, 2 = Servicios, 3 = Productos y Servicios
'DocTipo' => $docTipo, // 80 = CUIT, 96 = DNI, 99 = Consumidor Final
'DocNro' => $docNro,
'CbteDesde' => $proximoNro,
'CbteHasta' => $proximoNro,
'CbteFch' => $fechaHoy,
'ImpTotal' => $impTotal,
'ImpTotConc' => 0.00,
'ImpNeto' => round($impNeto, 2),
'ImpOpEx' => 0.00,
'ImpTrib' => 0.00,
'ImpIVA' => round($impIva, 2),
'MonId' => 'PES',
'MonCotiz' => 1.00,
'CondicionIVAReceptorId' => $condicionIvaReceptor, // Obligatorio RG 5616
];
if ($impIva > 0) {
$det['Iva'] = [
'AlicIva' => [
[
'Id' => 5, // 5 = 21%, 4 = 10.5%, 6 = 27%
'BaseImp' => round($impNeto, 2),
'Importe' => round($impIva, 2),
]
]
];
}
$res = $client->FECAESolicitar([
'Auth' => $auth,
'FeCAEReq' => [
'FeCabReq' => [
'CantReg' => 1,
'PtoVta' => $ptoVta,
'CbteTipo' => $cbteTipo,
],
'FeDetReq' => [
'FECAEDetRequest' => [$det],
],
],
]);
$detResp = $res->FECAESolicitarResult->FeDetResp->FECAEDetResponse;
if (is_array($detResp)) {
$detResp = $detResp[0];
}
if (($detResp->Resultado ?? 'R') !== 'A') {
throw new RuntimeException('Comprobante rechazado por ARCA: ' . json_encode($res->FECAESolicitarResult));
}
$cae = (string)$detResp->CAE;
$caeVto = (string)$detResp->CAEFchVto;
// 3. Generar URL del Código QR oficial RG 4892
$qrPayload = [
'ver' => 1,
'fecha' => date('Y-m-d'),
'cuit' => (int)$this->cuit,
'ptoVta' => $ptoVta,
'tipoCmp' => $cbteTipo,
'nroCmp' => $proximoNro,
'importe' => $impTotal,
'moneda' => 'PES',
'ctz' => 1,
'tipoDocRec' => $docTipo,
'nroDocRec' => $docNro,
'tipoCodAut' => 'E',
'codAut' => (int)$cae,
];
$qrUrl = 'https://www.afip.gob.ar/fe/qr/?p=' . base64_encode(json_encode($qrPayload, JSON_UNESCAPED_SLASHES));
return [
'nro_comprobante' => $proximoNro,
'cae' => $cae,
'cae_vencimiento' => $caeVto,
'qr_url_oficial' => $qrUrl,
];
}
}
4 Prompt listo para copiar: pedile tu facturador ARCA a MIA, Claude o Cursor
Tanto si contratás MIA (Desarrollo con IA de MESI) para que nuestro agente cree el sistema y lo deje hosteado en tu propia VPS, como si usás Claude Code, Cursor o Gemini CLI sobre tu Hosting NVMe, copiá este prompt para que la IA construya el flujo completo sin olvidar ninguna validación de ARCA:
Elegí dónde alojar o crear tu Facturación Electrónica ARCA en MESI
Todos nuestros planes corren sobre infraestructura Cloud propia con conectividad directa hacia wsaa.afip.gov.ar y servicios1.afip.gov.ar, incluyen ca-certificates-20261020, SoapClient y OpenSSL 3 listos de fábrica, se abonan en Pesos Argentinos con Factura A automática y cuentan con soporte especializado 24/7:
MIA (Desarrollo con IA)
Pedile a MIA que cree tu facturador ARCA + Mercado Pago o ERP a medida y dejalo corriendo en tu propia Cloud VPS dedicada sin programar.
Hosting Profesional NVMe
Discos NVMe Enterprise, PHP 8.4 con SoapClient y OpenSSL activos, SSL gratis y compatibilidad total con plugins de AFIP/ARCA para WordPress.
Cloud VPS 4
Recursos 100% dedicados con IP propia, acceso SSH root y almacenamiento SSD Enterprise RAID10 para alto volumen de facturación.
Preguntas frecuentes sobre Factura Electrónica ARCA (ex AFIP) y MIA
¿Cómo funciona MIA si quiero que la IA cree mi facturador ARCA/AFIP y lo aloje en una VPS?
Con MIA (Desarrollo con IA de MESI) tenés un entorno asistido por Antigravity Agent Manager y acompañado por especialistas reales de MESI. Le indicás en español cómo querés facturar (por ejemplo, desde una tienda online, un sistema de turnos o cobros de Mercado Pago), cargás tu certificado de ARCA y MIA deja el software programado, seguro y corriendo en tu propia Cloud VPS dedicada.
¿Qué significa el error "coe.alreadyAuthenticated" al conectar con WSAA?
Ocurre cuando tu aplicación ejecuta loginCms en cada venta sin reutilizar el Ticket de Acceso vigente. El ticket TA.xml de WSAA tiene una validez de 12 horas; guardalo en disco fuera de la carpeta pública y volvé a solicitar uno nuevo recién cuando falten menos de 10 minutos para su expiración.
¿Qué códigos lleva el campo obligatorio CondicionIVAReceptorId de la RG 5616?
En FECAESolicitar debés enviar dentro de cada comprobante el entero correspondiente a la condición frente al IVA del receptor: 1 (IVA Responsable Inscripto), 4 (IVA Sujeto Exento), 5 (Consumidor Final), 6 (Responsable Monotributo), 7 (Sujeto No Categorizado), 8 (Proveedor del Exterior), 9 (Cliente del Exterior), 10 (IVA Liberado – Ley 19.640), 13 (Monotributista Social) o 15 (IVA No Alcanzado).
¿Por qué en algunos servidores sin calibrar falla la conexión SOAP o SSL con wsaa.afip.gov.ar?
Suele ocurrir por tres motivos técnicos: falta de la extensión php-soap, un paquete ca-certificates desactualizado o la política estricta SECLEVEL=2 de OpenSSL 3 al negociar cifrados con los balanceadores de ARCA. En los servidores de MESI, PHP 8.4 ya trae SoapClient, OpenSSL 3 calibrado y ca-certificates-20261020 listos para conectar sin errores. Podés ver el detalle técnico en nuestra guía sobre cómo solucionar errores cURL SSL y ca-certificates con Mercado Pago y ARCA/AFIP.
Guías Técnicas Relacionadas
Solucionar cURL error 60 SSL con Mercado Pago y ARCA/AFIP
Cómo actualizar los 5 almacenes TLS (ca-certificates-20261020) y blindar el Checkout contra cobros duplicados.
Hosting en Pesos con Factura A vs Hosting en Dólares
Comparativa impositiva real para PyMEs argentinas: ahorro de 21% IVA Crédito Fiscal + 35% Ganancias.
Cómo conectar Claude, Cursor o ChatGPT al servidor MCP de MESI
Consultá dominios, planes y precios en tiempo real desde tu agente de IA mediante JSON-RPC 2.0.
MIA