Skip to content

Commit 52bc6a4

Browse files
committed
Initial official Java SDK
0 parents  commit 52bc6a4

31 files changed

Lines changed: 1707 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Java SDK CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
name: Test (Java 11, 17, 21)
12+
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
java: [11, 17, 21]
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Java
23+
uses: actions/setup-java@v4
24+
with:
25+
distribution: temurin
26+
java-version: ${{ matrix.java }}
27+
cache: maven
28+
29+
- name: Run tests
30+
run: mvn -B -ntp test

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# facturapi-java
2+
3+
Official Java SDK for [Facturapi](https://www.facturapi.io).
4+
5+
## Requirements
6+
7+
- Java 11+
8+
- Maven 3.8+
9+
10+
## Installation
11+
12+
```xml
13+
<dependency>
14+
<groupId>io.facturapi</groupId>
15+
<artifactId>facturapi-java</artifactId>
16+
<version>1.0.0</version>
17+
</dependency>
18+
```
19+
20+
## Quickstart
21+
22+
```java
23+
import com.facturapi.Facturapi;
24+
import java.util.Map;
25+
26+
Facturapi facturapi = new Facturapi("sk_test_...");
27+
28+
var customer = facturapi.customers.create(Map.of(
29+
"legal_name", "Mi Empresa SA de CV",
30+
"tax_id", "XAXX010101000",
31+
"tax_system", "601",
32+
"email", "cliente@example.com"
33+
), null);
34+
35+
var invoice = facturapi.invoices.create(Map.of(
36+
"customer", customer.get("id").asText(),
37+
"items", java.util.List.of(Map.of("quantity", 1, "product", "prod_123"))
38+
), null);
39+
```
40+
41+
## Configuration
42+
43+
```java
44+
Facturapi facturapi = Facturapi.builder("sk_test_...")
45+
.apiVersion("v2")
46+
.timeout(java.time.Duration.ofSeconds(20))
47+
.build();
48+
```
49+
50+
## Notes
51+
52+
- Uses `Authorization: Bearer <apiKey>`.
53+
- Supports custom base URL for integration testing.
54+
- Includes compatibility aliases (`all`, `del`, `lisLiveApiKeys`).

pom.xml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>io.facturapi</groupId>
7+
<artifactId>facturapi-java</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
<name>facturapi-java</name>
10+
<description>Official Java SDK for Facturapi</description>
11+
<url>https://github.com/facturapi/facturapi-java</url>
12+
13+
<licenses>
14+
<license>
15+
<name>MIT License</name>
16+
<url>https://opensource.org/licenses/MIT</url>
17+
</license>
18+
</licenses>
19+
20+
<properties>
21+
<maven.compiler.release>11</maven.compiler.release>
22+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23+
<jackson.version>2.17.2</jackson.version>
24+
<junit.version>5.11.0</junit.version>
25+
<okhttp.version>4.12.0</okhttp.version>
26+
</properties>
27+
28+
<dependencies>
29+
<dependency>
30+
<groupId>com.fasterxml.jackson.core</groupId>
31+
<artifactId>jackson-databind</artifactId>
32+
<version>${jackson.version}</version>
33+
</dependency>
34+
35+
<dependency>
36+
<groupId>org.junit.jupiter</groupId>
37+
<artifactId>junit-jupiter</artifactId>
38+
<version>${junit.version}</version>
39+
<scope>test</scope>
40+
</dependency>
41+
<dependency>
42+
<groupId>com.squareup.okhttp3</groupId>
43+
<artifactId>mockwebserver</artifactId>
44+
<version>${okhttp.version}</version>
45+
<scope>test</scope>
46+
</dependency>
47+
</dependencies>
48+
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<groupId>org.apache.maven.plugins</groupId>
53+
<artifactId>maven-surefire-plugin</artifactId>
54+
<version>3.3.0</version>
55+
<configuration>
56+
<useSystemClassLoader>true</useSystemClassLoader>
57+
</configuration>
58+
</plugin>
59+
</plugins>
60+
</build>
61+
</project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.facturapi;
2+
3+
public enum ApiVersion {
4+
V1("v1"),
5+
V2("v2");
6+
7+
private final String value;
8+
9+
ApiVersion(String value) {
10+
this.value = value;
11+
}
12+
13+
public String value() {
14+
return value;
15+
}
16+
17+
public static ApiVersion fromString(String raw) {
18+
if (raw == null) {
19+
return V2;
20+
}
21+
String normalized = raw.trim().toLowerCase();
22+
if ("v1".equals(normalized)) {
23+
return V1;
24+
}
25+
if ("v2".equals(normalized)) {
26+
return V2;
27+
}
28+
throw new IllegalArgumentException("Invalid API version. Valid values are: v1, v2");
29+
}
30+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.facturapi;
2+
3+
import com.facturapi.enums.CancellationMotive;
4+
import com.facturapi.enums.InvoiceType;
5+
import com.facturapi.enums.PaymentForm;
6+
import com.facturapi.enums.TaxFactor;
7+
import com.facturapi.enums.TaxType;
8+
import com.facturapi.http.FacturapiConfig;
9+
import com.facturapi.http.FacturapiHttpClient;
10+
import com.facturapi.resources.CustomersResource;
11+
import com.facturapi.resources.InvoicesResource;
12+
import com.facturapi.resources.OrganizationsResource;
13+
import com.facturapi.resources.ProductsResource;
14+
import com.facturapi.resources.ReceiptsResource;
15+
import com.facturapi.resources.RetentionsResource;
16+
import com.facturapi.resources.WebhooksResource;
17+
import com.facturapi.tools.CartaPorteCatalogsTool;
18+
import com.facturapi.tools.CatalogsTool;
19+
import com.facturapi.tools.ComercioExteriorCatalogsTool;
20+
import com.facturapi.tools.ToolsResource;
21+
import java.time.Duration;
22+
23+
public class Facturapi {
24+
private final FacturapiHttpClient httpClient;
25+
26+
public final CustomersResource customers;
27+
public final ProductsResource products;
28+
public final InvoicesResource invoices;
29+
public final OrganizationsResource organizations;
30+
public final ReceiptsResource receipts;
31+
public final RetentionsResource retentions;
32+
public final WebhooksResource webhooks;
33+
34+
public final CatalogsTool catalogs;
35+
public final CartaPorteCatalogsTool cartaPorteCatalogs;
36+
public final ComercioExteriorCatalogsTool comercioExteriorCatalogs;
37+
public final ToolsResource tools;
38+
39+
public Facturapi(String apiKey) {
40+
this(FacturapiConfig.builder(apiKey).build());
41+
}
42+
43+
// Backward-compatible constructor
44+
public Facturapi(String apiKey, String apiVersion) {
45+
this(FacturapiConfig.builder(apiKey).apiVersion(apiVersion).build());
46+
}
47+
48+
public Facturapi(FacturapiConfig config) {
49+
this.httpClient = new FacturapiHttpClient(config);
50+
this.customers = new CustomersResource(httpClient);
51+
this.products = new ProductsResource(httpClient);
52+
this.invoices = new InvoicesResource(httpClient);
53+
this.organizations = new OrganizationsResource(httpClient);
54+
this.receipts = new ReceiptsResource(httpClient);
55+
this.retentions = new RetentionsResource(httpClient);
56+
this.webhooks = new WebhooksResource(httpClient);
57+
58+
this.catalogs = new CatalogsTool(httpClient);
59+
this.cartaPorteCatalogs = new CartaPorteCatalogsTool(httpClient);
60+
this.comercioExteriorCatalogs = new ComercioExteriorCatalogsTool(httpClient);
61+
this.tools = new ToolsResource(httpClient);
62+
}
63+
64+
public static Builder builder(String apiKey) {
65+
return new Builder(apiKey);
66+
}
67+
68+
public static final class Builder {
69+
private final FacturapiConfig.Builder configBuilder;
70+
71+
private Builder(String apiKey) {
72+
this.configBuilder = FacturapiConfig.builder(apiKey);
73+
}
74+
75+
public Builder apiVersion(ApiVersion apiVersion) {
76+
this.configBuilder.apiVersion(apiVersion);
77+
return this;
78+
}
79+
80+
public Builder apiVersion(String apiVersion) {
81+
this.configBuilder.apiVersion(apiVersion);
82+
return this;
83+
}
84+
85+
public Builder baseUrl(String baseUrl) {
86+
this.configBuilder.baseUrl(baseUrl);
87+
return this;
88+
}
89+
90+
public Builder timeout(Duration timeout) {
91+
this.configBuilder.timeout(timeout);
92+
return this;
93+
}
94+
95+
public Builder userAgent(String userAgent) {
96+
this.configBuilder.userAgent(userAgent);
97+
return this;
98+
}
99+
100+
public Facturapi build() {
101+
return new Facturapi(configBuilder.build());
102+
}
103+
}
104+
105+
public static Class<PaymentForm> PaymentForm() {
106+
return PaymentForm.class;
107+
}
108+
109+
public static Class<TaxType> TaxType() {
110+
return TaxType.class;
111+
}
112+
113+
public static Class<TaxFactor> TaxFactor() {
114+
return TaxFactor.class;
115+
}
116+
117+
public static Class<InvoiceType> InvoiceType() {
118+
return InvoiceType.class;
119+
}
120+
121+
public static Class<CancellationMotive> CancellationMotive() {
122+
return CancellationMotive.class;
123+
}
124+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.facturapi;
2+
3+
public class FacturapiException extends RuntimeException {
4+
private final int statusCode;
5+
private final String responseBody;
6+
7+
public FacturapiException(String message) {
8+
super(message);
9+
this.statusCode = -1;
10+
this.responseBody = null;
11+
}
12+
13+
public FacturapiException(String message, Throwable cause) {
14+
super(message, cause);
15+
this.statusCode = -1;
16+
this.responseBody = null;
17+
}
18+
19+
public FacturapiException(String message, int statusCode, String responseBody) {
20+
super(message);
21+
this.statusCode = statusCode;
22+
this.responseBody = responseBody;
23+
}
24+
25+
public int getStatusCode() {
26+
return statusCode;
27+
}
28+
29+
public String getResponseBody() {
30+
return responseBody;
31+
}
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.facturapi.constants;
2+
3+
public final class FacturapiConstants {
4+
public static final String BASE_URL_V1 = "https://www.facturapi.io/v1";
5+
public static final String BASE_URL_V2 = "https://www.facturapi.io/v2";
6+
7+
private FacturapiConstants() {
8+
}
9+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.facturapi.enums;
2+
3+
public enum CancellationMotive {
4+
ERRORES_CON_RELACION("01"),
5+
ERRORES_SIN_RELACION("02"),
6+
NO_SE_CONCRETO("03"),
7+
FACTURA_GLOBAL("04");
8+
9+
private final String value;
10+
11+
CancellationMotive(String value) {
12+
this.value = value;
13+
}
14+
15+
public String value() {
16+
return value;
17+
}
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.facturapi.enums;
2+
3+
public enum InvoiceType {
4+
INGRESO("I"),
5+
EGRESO("E"),
6+
TRASLADO("T"),
7+
NOMINA("N"),
8+
PAGO("P");
9+
10+
private final String value;
11+
12+
InvoiceType(String value) {
13+
this.value = value;
14+
}
15+
16+
public String value() {
17+
return value;
18+
}
19+
}

0 commit comments

Comments
 (0)