Crear factura electrónica de AFIP en Java
Con pocas líneas de código
![Crear factura electrónica de AFIP en Java](/images/blog/java-create-invoice.png)
El primer paso para crear una factura electrónica de AFIP es obtener el Código de Autorización Electrónico o CAE.
Esto lo vamos a hacer utilizando Afip SDK que nos permite conectarnos a los web services de AFIP sin complicarnos con el uso de SOAP y la autenticación.
Vamos a user Gson para trabajar con JSON.
Añadimos la dependencia de Maven:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
Obtener la autorización
Lo primero que tenemos hacer es obtener el “Token authorization”, que seria la autorización en AFIP.
Para usar los web services de AFIP necesitamos un certificado y key pero Afip SDK nos deja utilizar el CUIT 20409378472 en modo testing para integrarnos rápidamente.
Debemos ejecutar una solicitud POST al endpoint
https://app.afipsdk.com/api/v1/afip/auth
package com.example;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
try {
// Paso 1: Obtener el Token Authorization
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
// Crear JSON para el request usando GSON
Map<String, String> authRequestMap = new HashMap<>();
authRequestMap.put("environment", "dev");
authRequestMap.put("tax_id", "20409378472");
authRequestMap.put("wsid", "wsfe");
Gson gson = new Gson();
String authRequestBody = gson.toJson(authRequestMap);
HttpRequest authRequest = HttpRequest.newBuilder()
.uri(new URI("https://app.afipsdk.com/api/v1/afip/auth"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(authRequestBody))
.build();
HttpResponse<String> authResponse = client.send(authRequest, HttpResponse.BodyHandlers.ofString());
if (authResponse.statusCode() >= 400) {
System.out.println("Error in auth request: " + authResponse.body());
return;
}
// Parsear respuesta para extraer el sign y token usando GSON
Type mapType = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> authData = gson.fromJson(authResponse.body(), mapType);
String token = authData.get("token");
String sign = authData.get("sign");
System.out.println("Token: " + token);
System.out.println("Sign: " + sign);
} catch (Exception e) {
e.printStackTrace();
}
}
}
En la pestaña “API” de la documentacion podes consultar todos los parametros del endpoint.
Ahora tenemos token y sign que nos dio AFIP para usar el web service. No es necesario que lo guardemos, Afip SDK se encarga de esto por nosotros, debemos solicitarlo antes de cada llamada a los métodos del web service.
Crear la factura
Vamos a crear una Factura B por un importe de $121. En el main de nuestra clase añadimos el siguiente codigo:
Debemos ejecutar una solicitud POST al endpoint
https://app.afipsdk.com/api/v1/afip/requests
// Obtener la fecha actual en formato yyyyMMdd
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String fechaActual = formatter.format(new Date());
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("environment", "dev");
payload.put("method", "FECAESolicitar");
payload.put("wsid", "wsfe");
Map<String, Object> auth = new LinkedHashMap<>();
auth.put("Token", token); // Replace with the actual token
auth.put("Sign", sign); // Replace with the actual sign
auth.put("Cuit", "20409378472");
Map<String, Object> feCabReq = new LinkedHashMap<>();
feCabReq.put("CantReg", 1);
feCabReq.put("PtoVta", 1);
feCabReq.put("CbteTipo", 6);
Map<String, Object> detRequest = new LinkedHashMap<>();
detRequest.put("Concepto", 1);
detRequest.put("DocTipo", 99);
detRequest.put("DocNro", 0);
detRequest.put("CbteDesde", 1);
detRequest.put("CbteHasta", 1);
detRequest.put("CbteFch", fechaActual);
detRequest.put("ImpTotal", 121);
detRequest.put("ImpTotConc", 0);
detRequest.put("ImpNeto", 100);
detRequest.put("ImpOpEx", 0);
detRequest.put("ImpIVA", 21);
detRequest.put("ImpTrib", 0);
detRequest.put("MonId", "PES");
detRequest.put("MonCotiz", 1);
Map<String, Object> iva = new LinkedHashMap<>();
iva.put("Id", 5);
iva.put("BaseImp", 100);
iva.put("Importe", 21);
detRequest.put("Iva", Map.of("AlicIva", List.of(iva)));
Map<String, Object> feDetReq = new LinkedHashMap<>();
feDetReq.put("FECAEDetRequest", List.of(detRequest));
Map<String, Object> feCAEReq = new LinkedHashMap<>();
feCAEReq.put("FeCabReq", feCabReq);
feCAEReq.put("FeDetReq", feDetReq);
Map<String, Object> params = new LinkedHashMap<>();
params.put("Auth", auth);
params.put("FeCAEReq", feCAEReq);
payload.put("params", params);
String invoiceRequestBody = gson.toJson(payload);
HttpRequest invoiceRequest = HttpRequest.newBuilder()
.uri(new URI("https://app.afipsdk.com/api/v1/afip/requests"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(invoiceRequestBody))
.build();
HttpResponse<String> invoiceResponse = client.send(invoiceRequest, HttpResponse.BodyHandlers.ofString());
if (invoiceResponse.statusCode() >= 400) {
System.out.println("Error in invoice request: " + invoiceResponse.body());
return;
}
System.out.println("Invoice Response: " + invoiceResponse.body());
En la pestaña “API” de la documentacion podes consultar todos los parametros del endpoint.
En invoiceData tenemos el CAE y vencimiento correspondientes a la factura que acabamos de crear.
{
...
"CAE": "12345678987654",
"CAEFchVto": "20240327"
...
}
Con la autorizacion creada ya podemos proceder a crear el PDF para presentarle a nuestro cliente. Podes usar como base esta factura o ticket de ejemplo.
Luego, lo único que nos queda es pasar a modo producción, para más información de cómo hacerlo pueden dirigirse a la documentación de la librería https://docs.afipsdk.com/