fluoroom/arca-sdk-php

PHP SDK for ARCA/AFIP SOAP web services (WSFEv1 invoicing + Padrón A13/A4/Constancia) — Laravel 12 ready

Maintainers

Package info

github.com/fluoroom/arca-sdk-php

pkg:composer/fluoroom/arca-sdk-php

Transparency log

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.1 2026-07-29 05:33 UTC

This package is auto-updated.

Last update: 2026-07-29 05:35:03 UTC


README

PHP SDK para los servicios web de ARCA/AFIP, orientado a Laravel 12.

Cubre los servicios de facturación electrónica (WSFEv1, 22 métodos) y consulta a padrón (Alcance 13, Alcance 4, Constancia de Inscripción), con autenticación WSAA transparente y una API tipada y amigable para el desarrollador.

Requisitos

Dependencia Versión mínima
PHP 8.2
ext-soap *
ext-openssl *
ext-simplexml *
Laravel (opcional) 12.x

Instalación

composer require fluoroom/arca-sdk-php

Laravel registra el service provider automáticamente vía Package Auto-Discovery. Para publicar la configuración:

php artisan vendor:publish --tag=arca-config

Configuración

Variables de entorno

El SDK soporta credenciales independientes para homologación y producción. Las variables ARCA_CUIT / ARCA_CERT_PATH / ARCA_KEY_PATH actúan como fallback cuando ambos entornos comparten el mismo certificado.

# Entorno por defecto al llamar sin env() explícito
ARCA_ENVIRONMENT=homologacion   # o produccion

# ── Homologación ───────────────────────────────────────────────
ARCA_HOMO_CUIT=30111111112
ARCA_HOMO_CERT_PATH=/ruta/homo/cert.pem
ARCA_HOMO_KEY_PATH=/ruta/homo/clave.key

# ── Producción ─────────────────────────────────────────────────
ARCA_PROD_CUIT=30111111112
ARCA_PROD_CERT_PATH=/ruta/prod/certP.crt
ARCA_PROD_KEY_PATH=/ruta/prod/claveP.key

# ── Opcionales ─────────────────────────────────────────────────
ARCA_CACHE_STORE=               # Store de caché Laravel (vacío = default)
ARCA_TIMEOUT=30
ARCA_WSDL_CACHE=true

Si solo usás un entorno, podés usar las variables genéricas de fallback:

ARCA_CUIT=30111111112
ARCA_CERT_PATH=/ruta/cert.pem
ARCA_KEY_PATH=/ruta/clave.key

WSFEv1 — Facturación electrónica

Inicio rápido (Laravel)

use Arca\Sdk\Facades\Wsfe;
use Arca\Sdk\Enums\Environment;
use Arca\Sdk\Dto\Invoice;

// Health check (sin autenticación)
$status = Wsfe::ping();
echo $status->appServer; // "OK"

// Consultar catálogos desde producción (datos reales)
$tipos = Wsfe::env(Environment::Produccion)->getComprobanteTypes();
$ptos  = Wsfe::env(Environment::Produccion)->getPuntosVenta();

// Autorizar una Factura C en homologación
$last    = Wsfe::env(Environment::Homologacion)->getLastAuthorized(ptoVta: 1, cbteTipo: 11);
$nextNro = $last->nextNumber();

$invoice = new Invoice(
    concepto:               1,
    docTipo:                96,           // DNI
    docNro:                 '12345678',
    cbteDesde:              $nextNro,
    cbteHasta:              $nextNro,
    impTotal:               1000.00,
    impTotConc:             0.00,
    impNeto:                1000.00,      // Para clase C: subtotal va en impNeto
    impOpEx:                0.00,
    impTrib:                0.00,
    impIVA:                 0.00,         // Clase C no lleva IVA
    monId:                  'PES',
    monCotiz:               1.0,
    condicionIvaReceptorId: 5,            // Consumidor Final
    cbteFch:                date('Ymd'),
);

$result = Wsfe::env(Environment::Produccion)->authorizeInvoice(ptoVta: 1, cbteTipo: 11, invoice: $invoice);

if ($result->isApproved()) {
    $detail = $result->details[0];
    echo "CAE: {$detail->cae}";
    echo "Vto: {$detail->caeFchVto}";
}

Uso sin Laravel

use Arca\Sdk\Enums\Environment;
use Arca\Sdk\Wsaa\WsaaClient;
use Arca\Sdk\Wsaa\CachedTokenProvider;
use Arca\Sdk\WsfeClient;

$wsaa  = new WsaaClient(certPath: '/ruta/cert.pem', keyPath: '/ruta/clave.key');
$token = new CachedTokenProvider($wsaa, $cache, '/ruta/cert.pem');
$wsfe  = new WsfeClient(tokenProvider: $token, cuit: '30111111112', environment: Environment::Produccion);

$result = $wsfe->authorizeInvoice(ptoVta: 1, cbteTipo: 11, invoice: $invoice);

Referencia de métodos — WSFEv1

Método PHP SOAP Descripción
ping() FEDummy Health check (sin auth)
authorizeInvoice(...) FECAESolicitar Autorizar comprobante por CAE
authorizeInvoiceBatch(...) FECAESolicitar Autorizar lote de comprobantes
requestCaea(periodo, orden) FECAEASolicitar Solicitar CAEA para una quincena
getCaea(periodo, orden) FECAEAConsultar Consultar CAEA otorgado
reportCaeaNoMovement(ptoVta, caea) FECAEASinMovimientoInformar Informar CAEA sin movimiento
reportCaeaInvoice(...) FECAEARegInformativo Informar comprobante emitido bajo CAEA
reportCaeaInvoiceBatch(...) FECAEARegInformativo Informar lote bajo CAEA
getCaeaNoMovement(caea, ptoVta) FECAEASinMovimientoConsultar Consultar comprobantes sin movimiento
getLastAuthorized(ptoVta, cbteTipo) FECompUltimoAutorizado Último número autorizado
getMaxRecordsPerRequest() FECompTotXRequest Máximo de registros por request
getInvoice(ptoVta, cbteTipo, cbteNro) FECompConsultar Consultar comprobante autorizado
getComprobanteTypes() FEParamGetTiposCbte Tipos de comprobante
getConceptoTypes() FEParamGetTiposConcepto Tipos de concepto
getDocTypes() FEParamGetTiposDoc Tipos de documento
getIvaTypes() FEParamGetTiposIva Alícuotas de IVA
getCurrencies() FEParamGetTiposMonedas Monedas
getOptionalTypes() FEParamGetTiposOpcional Tipos opcionales (RG específicos)
getTributeTypes() FEParamGetTiposTributos Tipos de tributos
getPuntosVenta() FEParamGetPtosVenta Puntos de venta del contribuyente
getCotizacion(monId) FEParamGetCotizacion Cotización de referencia AFIP
getPaises() FEParamGetTiposPaises Países
getActividades() FEParamGetActividades Actividades del contribuyente
getCondicionIvaReceptor(clase?) FEParamGetCondicionIvaReceptor Condiciones IVA del receptor

Padrón — Consulta de contribuyentes

PadronClient expone tres sub-servicios bajo una misma interfaz: Alcance 13 (identificación), Alcance 4 (situación tributaria completa) y Constancia de Inscripción. Cada sub-servicio obtiene su propio ticket WSAA de forma transparente.

¿Qué servicio usar?

Necesidad Sub-servicio
Verificar si un CUIT existe/está activo y obtener nombre/domicilio a13
Conocer impuestos, regímenes, actividades y relaciones de un CUIT a4
Reproducir/validar la Constancia de Inscripción oficial (monotributo, categoría, caracterizaciones) constancia

Uso

use Arca\Sdk\PadronClient;
use Arca\Sdk\Enums\Environment;
use Arca\Sdk\Wsaa\WsaaClient;
use Arca\Sdk\Wsaa\CachedTokenProvider;

// Cada sub-servicio requiere su propio ticket WSAA (service id distinto)
$mkProvider = fn(string $service) => new CachedTokenProvider(
    wsaaClient: new WsaaClient(certPath: '/ruta/cert.pem', keyPath: '/ruta/clave.key', service: $service),
    cache:      $cache,
    certPath:   '/ruta/cert.pem',
    service:    $service,
);

$padron = new PadronClient(
    a13Provider:        $mkProvider('ws_sr_padron_a13'),
    a4Provider:         $mkProvider('ws_sr_padron_a4'),
    constanciaProvider: $mkProvider('ws_sr_constancia_inscripcion'),
    cuit:               '30111111112',
    environment:        Environment::Produccion,
);

// ── Alcance 13: identificación rápida ──────────────────────────
$persona = $padron->a13->getPersona('20304050607');
echo $persona->razonSocial ?? "{$persona->apellido}, {$persona->nombre}";
echo $persona->estadoClave; // "ACTIVO"

// Resolver DNI → CUIT/CUIL/CDI
$ids = $padron->a13->getIdsByDocumento('30123456');

// ── Alcance 4: situación tributaria completa ───────────────────
$persona = $padron->a4->getPersona('20304050607');
foreach ($persona->impuesto as $imp) {
    echo "{$imp->descripcionImpuesto}: {$imp->estado}";
}

// ── Constancia de Inscripción ──────────────────────────────────
$constancia = $padron->constancia->getPersona('20304050607');

if ($constancia->hasError()) {
    echo $constancia->errorConstancia->error;
} else {
    $general = $constancia->datosGenerales;
    echo $general->razonSocial ?? "{$general->apellido}, {$general->nombre}";

    // Verificar si es monotributista
    if ($constancia->isMonotributista()) {
        $cat = $constancia->datosMonotributo->categoriaMonotributo[0] ?? null;
        echo "Categoría: {$cat?->descripcionCategoria}";
    }

    // Ganancias simplificada (RG 4.6)
    if ($constancia->hasSimplifiedGananciasRegime()) {
        echo "Adherido a Ganancias Simplificada";
    }
}

// Consulta en lote — hasta 250 CUITs por llamada, se pagina automáticamente
$results = $padron->constancia->getPersonaBatch(['20304050607', '27123456789', '30500010459']);
foreach ($results as $cuit => $r) {
    echo "$cuit: " . ($r->hasError() ? $r->errorConstancia->error : 'OK');
}

Manejo de errores

Los métodos de ítem único (getPersona) lanzan excepciones tipadas ante faults SOAP. Los métodos de lista (getPersonaBatch) nunca lanzan por ítem individual — los errores se expresan como errorConstancia dentro de cada PersonaConstancia devuelta.

use Arca\Sdk\Exceptions\PadronNotFoundError;
use Arca\Sdk\Exceptions\PadronInactiveError;
use Arca\Sdk\Exceptions\PadronAuthError;
use Arca\Sdk\Exceptions\PadronException;

try {
    $persona = $padron->a13->getPersona('00000000000');
} catch (PadronNotFoundError $e) {
    // CUIT inexistente
} catch (PadronInactiveError $e) {
    // CUIT inactivo
} catch (PadronAuthError $e) {
    // Token/sign inválido o CUIT representada no autorizado
} catch (PadronException $e) {
    // Otro error de padrón
}

Referencia de métodos — Padrón

Sub-servicio Método PHP SOAP Descripción
a13 ping() dummy Health check
a13 getPersona(cuit) getPersona Identificación + domicilios
a13 getIdsByDocumento(doc) getIdPersonaListByDocumento Resolver DNI → CUIT/CUIL/CDI
a4 ping() dummy Health check
a4 getPersona(cuit) getPersona Situación tributaria completa
constancia ping() dummy Health check
constancia getPersona(cuit) getPersona_v2 Constancia de inscripción (un CUIT)
constancia getPersonaBatch(cuits[]) getPersonaList_v2 Constancia en lote (≤250, paginado automático)

Testing

# Todas las suites
./vendor/bin/phpunit

# Por servicio
./vendor/bin/phpunit --testsuite wsaa
./vendor/bin/phpunit --testsuite wsfe
./vendor/bin/phpunit --testsuite padron

# Producción (solo lectura, sin emisión)
./vendor/bin/phpunit --testsuite wsfe-prod

Requiere afipSec/ssl/cert.pem y afipSec/ssl/clave.key. El token de 12 horas se persiste automáticamente en afipSec/tokens/ para no consumir el cooldown de WSAA entre ejecuciones.

Licencia

MIT