diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java
index 960acb8..e91997f 100644
--- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java
+++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java
@@ -4,6 +4,7 @@ import com.teterialosjuanjos.tfg.sync_service.config.IntegrationProperties;
import com.teterialosjuanjos.tfg.sync_service.integration.prestashop.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
@@ -84,6 +85,7 @@ public class PrestashopClient {
/**
* Creates a new product in PrestaShop.
+ * PS WebService requires XML request body even when {@code output_format=JSON} is set.
*
* @return the created product including its assigned {@code id}
*/
@@ -94,7 +96,8 @@ public class PrestashopClient {
.queryParam("ws_key", wsKey)
.queryParam("output_format", "JSON")
.build())
- .body(new PrestashopProductDto.SingleResponse(dto))
+ .contentType(MediaType.APPLICATION_XML)
+ .body(toProductXml(dto))
.retrieve()
.body(PrestashopProductDto.SingleResponse.class);
@@ -109,7 +112,8 @@ public class PrestashopClient {
.queryParam("ws_key", wsKey)
.queryParam("output_format", "JSON")
.build(id))
- .body(new PrestashopProductDto.SingleResponse(dto))
+ .contentType(MediaType.APPLICATION_XML)
+ .body(toProductXml(dto))
.retrieve()
.toBodilessEntity();
}
@@ -147,7 +151,8 @@ public class PrestashopClient {
.queryParam("ws_key", wsKey)
.queryParam("output_format", "JSON")
.build(id))
- .body(new PrestashopStockAvailableDto.SingleResponse(dto))
+ .contentType(MediaType.APPLICATION_XML)
+ .body(toStockAvailableXml(dto))
.retrieve()
.toBodilessEntity();
}
@@ -194,4 +199,80 @@ public class PrestashopClient {
.body(PrestashopCustomerDto.SingleResponse.class);
return response != null ? response.customer() : null;
}
+
+ // ── XML builders ──────────────────────────────────────────────────────
+ // PS WebService requires XML body for writes; output_format=JSON only affects the response.
+
+ private String toProductXml(PrestashopProductDto dto) {
+ String name = firstLangValue(dto.name());
+ String description = firstLangValue(dto.description());
+ String descShort = firstLangValue(dto.descriptionShort());
+ String slug = toSlug(dto.reference());
+
+ StringBuilder sb = new StringBuilder(512);
+ sb.append("");
+ sb.append("");
+ sb.append("");
+ if (dto.id() != null) {
+ sb.append("").append(dto.id()).append("");
+ }
+ sb.append("").append(escapeXml(dto.reference())).append("");
+ if (dto.price() != null) {
+ sb.append("").append(escapeXml(dto.price())).append("");
+ }
+ if (dto.active() != null) {
+ sb.append("").append(escapeXml(dto.active())).append("");
+ }
+ if (dto.idCategoryDefault() != null) {
+ sb.append("").append(escapeXml(dto.idCategoryDefault())).append("");
+ }
+ sb.append("1");
+ sb.append("").append(escapeXml(slug)).append("");
+ sb.append("").append(escapeXml(name)).append("");
+ sb.append("").append(escapeXml(description)).append("");
+ sb.append("").append(escapeXml(descShort)).append("");
+ sb.append("");
+ sb.append("");
+ return sb.toString();
+ }
+
+ private String toStockAvailableXml(PrestashopStockAvailableDto dto) {
+ StringBuilder sb = new StringBuilder(256);
+ sb.append("");
+ sb.append("");
+ sb.append("");
+ if (dto.id() != null) {
+ sb.append("").append(dto.id()).append("");
+ }
+ if (dto.idProduct() != null) {
+ sb.append("").append(dto.idProduct()).append("");
+ }
+ String idAttr = dto.idProductAttribute() != null ? dto.idProductAttribute() : "0";
+ sb.append("").append(idAttr).append("");
+ sb.append("").append(dto.quantity()).append("");
+ sb.append("");
+ sb.append("");
+ return sb.toString();
+ }
+
+ private static String firstLangValue(List langs) {
+ if (langs == null || langs.isEmpty()) return "";
+ String v = langs.get(0).value();
+ return v != null ? v : "";
+ }
+
+ /** Generates a URL-safe slug from any string (used for PS link_rewrite). */
+ private static String toSlug(String text) {
+ if (text == null || text.isBlank()) return "product";
+ return text.toLowerCase().replaceAll("[^a-z0-9]+", "-").replaceAll("^-|-$", "");
+ }
+
+ private static String escapeXml(String text) {
+ if (text == null) return "";
+ return text.replace("&", "&")
+ .replace("<", "<")
+ .replace(">", ">")
+ .replace("\"", """)
+ .replace("'", "'");
+ }
}