Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2479,7 +2479,7 @@ namespace ExampleReadme
<summary>Emisión Timbrado (IssueV4)</summary>

**Ejemplo del consumo de la librería para el servicio IssueV4 (PDF) Json en formato string mediante usuario y contraseña.**
```cs
```java

import Services.Issue.SWIssueService;
import Utils.Responses.Stamp.SuccessV1Response;
Expand Down Expand Up @@ -2546,7 +2546,72 @@ public class ExampleReadme {
SWIssueServiceV4 stamp = new SWIssueServiceV4("tokenUser", "http://services.test.sw.com.mx");
```
</details>
----------------

# Timbrado Retenciones #
<details><summary><b>Timbrado Retenciones</b></summary>

<br>Recibe el contenido de un XML ya emitido (sellado) en formato String, posteriormente si la factura y el token son correctos devuelve el CFDI timbrado, en caso contrario lanza una excepción.

Este método recibe los siguientes parámetros:
* Archivo en formato **String** ó **Base64**
* Usuario y contraseña ó Token
* Url Servicios SW

**Ejemplo de consumo de la librería para timbrar XML en formato string utilizando usuario y contraseña**
```java
import Utils.Responses.StampRetention.SuccessV3Response;
import Services.StampRetention.SWStampRetentionService;

public class ExampleReadme {
public static void main(String[] args) {
try {
// Inicializar el objeto con la información de la cuenta y especifica la URL base para acceder al entorno deseado
SWStampRetentionService api = new SWStampRetentionService("user", "password", "http://services.test.sw.com.mx");
// Inicializar un objeto de respuesta para almacenar la respuesta
SuccessV3Response response = null;
//Se llama al método StampRetention y se envia el xml y versión de respuesta
response = (SuccessV3Response) api.StampRetention(stringXML, "v3");
// En response se mostrará la informacion de respuesta del servicio
System.out.println(response.Status);
System.out.println(response.HttpStatusCode);
System.out.println(response.retencion);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```

**Ejemplo de consumo de la librería para timbrar XML en formato string utilizando token** [¿Como obtener token?](http://developers.sw.com.mx/knowledge-base/generar-un-token-infinito/)
```java
import Utils.Responses.StampRetention.SuccessV3Response;
import Services.StampRetention.SWStampRetentionService;

public class ExampleReadme {
public static void main(String[] args) {
try {
// Inicializar el objeto con la información del token de acceso y especifica la URL base para acceder al entorno deseado
SWStampRetentionService api = new SWStampRetentionService("tokenUser", "http://services.test.sw.com.mx");
// Inicializar un objeto de respuesta para almacenar la respuesta
SuccessV3Response response = null;
//Se llama al método StampRetention y se envia el xml y versión de respuesta
response = (SuccessV3Response) api.StampRetention(stringXML, "v3");
// En response se mostrará la informacion de respuesta del servicio
System.out.println(response.Status);
System.out.println(response.HttpStatusCode);
System.out.println(response.retencion);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```

</details>

| Version | Respuesta |
|---------|---------------------------------------------------------------|
| V3 | Devuelve el CFDI timbrado |


Para mayor referencia de un listado completo de los servicios favor de visitar nuestro [sitio developers](https://developers.sw.com.mx/).
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
</properties>
<artifactId>SW-JAVA</artifactId>
<version>1.0.21.3</version>
<version>1.0.22.1</version>
<packaging>jar</packaging>
<scm>
<url>https://github.com/lunasoft/sw-sdk-java</url>
Expand Down
128 changes: 128 additions & 0 deletions src/main/java/Services/StampRetention/SWStampRetentionService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package Services.StampRetention;
import java.io.IOException;
import java.nio.charset.Charset;

import Exceptions.AuthException;
import Exceptions.GeneralException;
import Services.SWService;
import Utils.Requests.StampRetention.StampRetentionOptionsRequest;
import Utils.Requests.StampRetention.StampRetentionRequest;
import Utils.Responses.IResponse;

public class SWStampRetentionService extends SWService {

public SWStampRetentionService(String user, String password, String URI) throws AuthException {
super(user, password, URI);
}

public SWStampRetentionService(String token, String URI) {
super(token, URI);
}

public SWStampRetentionService(String user, String password, String URI, String proxyHost, int proxyPort)
throws AuthException {
super(user, password, URI, proxyHost, proxyPort);
}

public SWStampRetentionService(String token, String URI, String proxyHost, int proxyPort) {
super(token, URI, proxyHost, proxyPort);
}

/**
* Servicio para timbrar un CFDI de retenciones en formato XML.
*
* Realiza el timbrado de un CFDI de retenciones en formato XML.
*
* @param xml String del CFDI en formato XML.
* @param version Versión del servicio.
* @return Respuesta del servicio.
* @throws AuthException Excepción de autenticación.
* @throws GeneralException Excepción general.
* @throws IOException Excepción de entrada/salida.
*/
public IResponse StampRetention(String xml, String version) throws AuthException, GeneralException, IOException{
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xml, version, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}

/**
* Servicio para timbrar un CFDI de retenciones en formato XML o Base64 dependiendo de la
* bandera isb64.
*
* Realiza el timbrado de un CFDI de retenciones en formato XML.
*
* @param xml String del CFDI en formato XML.
* @param version Versión del servicio.
* @param isb64 Bandera que indica si el XML está en formato Base64.
* @return Respuesta del servicio.
* @throws AuthException Excepción de autenticación.
* @throws GeneralException Excepción general.
* @throws IOException Excepción de entrada/salida.
*/
public IResponse StampRetention(String xml, String version, boolean isb64) throws AuthException, GeneralException, IOException{
if (isb64){
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xml, version, isb64, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}
else{
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xml, version, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}
}

/**
* Servicio para timbrar un CFDI de retenciones en formato XML a partir de un archivo byte[]
*
* Realiza el timbrado de un CFDI de retenciones en formato XML.
*
* @param xmlFile Arreglo de bytes que representa el archivo XML o Base64 del CFDI de retención.
* @param version Versión del servicio.
* @return Respuesta del servicio.
* @throws AuthException Excepción de autenticación.
* @throws GeneralException Excepción general.
* @throws IOException Excepción de entrada/salida.
*/
public IResponse StampRetention(byte[] xmlFile, String version) throws AuthException, GeneralException, IOException{
String xmlProcess = new String(xmlFile, Charset.forName("UTF-8"));
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xmlProcess, version, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}

/**
* Servicio para timbrar un CFDI de retenciones en formato XML a partir de un archivo byte[] o
* Base64.
*
* Realiza el timbrado de un CFDI de retenciones en formato XML.
*
* @param xmlFile Arreglo de bytes que representa el archivo XML o Base64 del CFDI de retención.
* @param version Versión del servicio.
* @param isb64 Bandera que indica si el XML está en formato Base64.
* @return Respuesta del servicio.
* @throws AuthException Excepción de autenticación.
* @throws GeneralException Excepción general.
* @throws IOException Excepción de entrada/salida.
*/
public IResponse StampRetention(byte[] xmlFile, String version, boolean isb64) throws AuthException, GeneralException, IOException{
String xmlProcess = new String(xmlFile, Charset.forName("UTF-8"));
if (isb64){
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xmlProcess, version, isb64, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}
else{
StampRetentionOptionsRequest settings = new StampRetentionOptionsRequest(getToken(), getURI(), xmlProcess, version, getProxyHost(),
getProxyPort());
StampRetentionRequest req = new StampRetentionRequest();
return req.sendRequest(settings);
}
}
}
1 change: 1 addition & 0 deletions src/main/java/Utils/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class Constants {
public static String BASE_PATH = "https://services.test.sw.com.mx";
public static String AUTH_PATH_V2 = "/v2/security/authenticate";
public static String STAMP_PATH = "/cfdi33/stamp/";
public static String STAMP_RETENTION_PATH = "/retencion/stamp/";
public static String STAMP_ZIP_PATH = "/cfdi/stamp/v1/zip/";
public static String STAMP_V2_PATH = "/cfdi33/v2/stamp/";
public static String ISSUE_JSON_PATH = "/v3/cfdi33/issue/json/";
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/Utils/Helpers/BuildRetentionResponseV3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package Utils.Helpers;
import org.json.JSONObject;
import Utils.Responses.IResponse;
import Utils.Responses.StampRetention.SuccessV3Response;

public class BuildRetentionResponseV3 extends ResponseStamp {
public IResponse getResponse(){
if(!response.trim().isEmpty() && status < 500){
JSONObject body = new JSONObject(response);
if(status == 200){
JSONObject data = body.getJSONObject("data");
return new SuccessV3Response(status, body.getString("status"), data.getString("retencion"), "OK", "OK");
}
else{
String messageDetail = "";
if (!body.isNull("messageDetail")){
messageDetail = body.getString("messageDetail");
}
if(body.getString("message").equals("307. El comprobante contiene un timbre previo.")) {
if(!body.isNull("data")) {
JSONObject data = body.getJSONObject("data");
return new SuccessV3Response(status, body.getString("status"), data.getString("retencion"), body.getString("message"), messageDetail);
}
}
return new SuccessV3Response(status, body.getString("status"), "", body.getString("message"), messageDetail);
}
}
else {
return new SuccessV3Response(status, "error", "","Error con código "+status+": "+reason.getReasonPhrase(), response);
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/Utils/Helpers/ResponseStampRetentionBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package Utils.Helpers;

public class ResponseStampRetentionBuilder {
public static ResponseStamp StampedRetention(char version){
switch(version){
case '3': return new BuildRetentionResponseV3();
default: return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package Utils.Requests.StampRetention;
import Utils.Constants;
import Utils.Requests.IRequest;

public class StampRetentionOptionsRequest extends IRequest{
private String xml;

public StampRetentionOptionsRequest(String token, String URI, String xml, String version, String proxyHost, int proxyPort){
super(token, URI + Constants.STAMP_RETENTION_PATH + version, xml, version, proxyHost, proxyPort);
this.xml = xml;
}

public StampRetentionOptionsRequest(String token, String URI, String xml, String version, boolean isb64, String proxyHost, int proxyPort){
super(token, URI + Constants.STAMP_RETENTION_PATH + version + "/b64", xml, version, proxyHost, proxyPort);
this.xml = xml;
}

public String getXml() {
return xml;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package Utils.Requests.StampRetention;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.UUID;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MIME;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import Exceptions.AuthException;
import Exceptions.GeneralException;
import Utils.Helpers.RequestHelper;
import Utils.Helpers.ResponseStamp;
import Utils.Helpers.ResponseStampRetentionBuilder;
import Utils.Requests.IRequest;
import Utils.Requests.IRequestor;
import Utils.Responses.IResponse;

public class StampRetentionRequest implements IRequestor {

public IResponse sendRequest(IRequest request) throws GeneralException, AuthException {
try {
String xmlStr = ((StampRetentionOptionsRequest) request).getXml();
String boundary = UUID.randomUUID().toString();
String raw = "--" + boundary
+ "\r\nContent-Disposition: form-data; name=xml; filename=xml\r\nContent-Type: application/xml\r\n\r\n"
+ xmlStr + "\r\n--" + boundary + "--";
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httppost = new HttpPost(request.URI);
RequestHelper.setTimeOut(request.options, raw.length());
RequestHelper.setProxy(request.options, request.proxyHost, request.proxyPort);
httppost.setConfig(request.options.build());
httppost.setHeader("Authorization", "bearer " + request.Token);
httppost.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
httppost.addHeader("Content-Disposition", "form-data; name=xml; filename=xml");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
Charset chars = Charset.forName("UTF-8");
builder.setCharset(chars);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("xml", raw, ContentType.create("text/plain", MIME.UTF8_CHARSET));
httppost.setEntity(builder.build());
CloseableHttpResponse responseB = client.execute(httppost);
HttpEntity entity = responseB.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
int status = responseB.getStatusLine().getStatusCode();
client.close();
responseB.close();
ResponseStamp R = ResponseStampRetentionBuilder.StampedRetention(request.version.charAt(request.version.length() - 1));
R.setReason(responseB.getStatusLine());
R.setResponse(responseString);
R.setStatus(status);
return R.getResponse();

} catch (JSONException e) {
throw new GeneralException(500, e.getMessage());
} catch (IOException e) {
e.printStackTrace();
throw new GeneralException(500, e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package Utils.Responses.StampRetention;
import Utils.Responses.IResponse;

public class SuccessV3Response extends IResponse{
public String retencion;
public SuccessV3Response(int httpStatusCode, String status, String _retencion, String msg, String msgDetail) {
super(httpStatusCode, status, msg, msgDetail);
this.retencion = _retencion;
}
}
Loading