fix: send XML body on PS WebService write operations
PS WebService requires XML request body even when output_format=JSON. Build XML manually in PrestashopClient for createProduct, updateProduct and updateStockAvailable. Add link_rewrite slug generation and XML character escaping. Response parsing (JSON) unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
588c1db5c3
commit
cfce84eb4d
|
|
@ -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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
sb.append("<prestashop xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
sb.append("<product>");
|
||||
if (dto.id() != null) {
|
||||
sb.append("<id>").append(dto.id()).append("</id>");
|
||||
}
|
||||
sb.append("<reference>").append(escapeXml(dto.reference())).append("</reference>");
|
||||
if (dto.price() != null) {
|
||||
sb.append("<price>").append(escapeXml(dto.price())).append("</price>");
|
||||
}
|
||||
if (dto.active() != null) {
|
||||
sb.append("<active>").append(escapeXml(dto.active())).append("</active>");
|
||||
}
|
||||
if (dto.idCategoryDefault() != null) {
|
||||
sb.append("<id_category_default>").append(escapeXml(dto.idCategoryDefault())).append("</id_category_default>");
|
||||
}
|
||||
sb.append("<id_tax_rules_group>1</id_tax_rules_group>");
|
||||
sb.append("<link_rewrite><language id=\"1\">").append(escapeXml(slug)).append("</language></link_rewrite>");
|
||||
sb.append("<name><language id=\"1\">").append(escapeXml(name)).append("</language></name>");
|
||||
sb.append("<description><language id=\"1\">").append(escapeXml(description)).append("</language></description>");
|
||||
sb.append("<description_short><language id=\"1\">").append(escapeXml(descShort)).append("</language></description_short>");
|
||||
sb.append("</product>");
|
||||
sb.append("</prestashop>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String toStockAvailableXml(PrestashopStockAvailableDto dto) {
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
sb.append("<prestashop xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
|
||||
sb.append("<stock_available>");
|
||||
if (dto.id() != null) {
|
||||
sb.append("<id>").append(dto.id()).append("</id>");
|
||||
}
|
||||
if (dto.idProduct() != null) {
|
||||
sb.append("<id_product>").append(dto.idProduct()).append("</id_product>");
|
||||
}
|
||||
String idAttr = dto.idProductAttribute() != null ? dto.idProductAttribute() : "0";
|
||||
sb.append("<id_product_attribute>").append(idAttr).append("</id_product_attribute>");
|
||||
sb.append("<quantity>").append(dto.quantity()).append("</quantity>");
|
||||
sb.append("</stock_available>");
|
||||
sb.append("</prestashop>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String firstLangValue(List<PrestashopProductDto.LangValue> 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("'", "'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue