Refactor PrestashopClient to normalize base URL, enhance URL building, and improve raw query handling
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
// package à adapter si besoin
|
||||||
package fr.gameovergne.api.service;
|
package fr.gameovergne.api.service;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -19,166 +20,133 @@ import java.util.Map;
|
|||||||
public class PrestashopClient {
|
public class PrestashopClient {
|
||||||
|
|
||||||
private final RestClient client;
|
private final RestClient client;
|
||||||
private final String baseUrl; // ex: https://shop.gameovergne.fr/api
|
private final String baseUrl;
|
||||||
private final String apiKey;
|
private final String apiKey;
|
||||||
|
|
||||||
public PrestashopClient(
|
public PrestashopClient(
|
||||||
@Value("${prestashop.api.base-url}") String baseUrl,
|
@Value("${prestashop.api.base-url}") String baseUrl,
|
||||||
@Value("${prestashop.api.key}") String apiKey
|
@Value("${prestashop.api.key}") String apiKey
|
||||||
) {
|
) {
|
||||||
// on normalise pour éviter les doubles /
|
this.baseUrl = baseUrl; // ex: https://shop.gameovergne.fr/api
|
||||||
if (baseUrl.endsWith("/")) {
|
|
||||||
this.baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
|
|
||||||
} else {
|
|
||||||
this.baseUrl = baseUrl;
|
|
||||||
}
|
|
||||||
this.apiKey = apiKey;
|
this.apiKey = apiKey;
|
||||||
|
|
||||||
log.info("[PrestaShop] Base URL = {}", this.baseUrl);
|
log.info("[PrestaShop] Base URL = {}", baseUrl);
|
||||||
log.info("[PrestaShop] API key length = {}", apiKey != null ? apiKey.length() : 0);
|
log.info("[PrestaShop] API key length = {}", apiKey.length());
|
||||||
|
|
||||||
this.client = RestClient.builder()
|
this.client = RestClient.builder()
|
||||||
.defaultHeaders(headers -> {
|
.defaultHeaders(headers -> {
|
||||||
headers.set(HttpHeaders.USER_AGENT, "curl/8.10.1");
|
headers.set(HttpHeaders.USER_AGENT, "curl/8.10.1");
|
||||||
// Accept JSON par défaut ; pour XML on surchargera dans les méthodes XML
|
|
||||||
headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.ALL));
|
headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.ALL));
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String normalizePath(String path) {
|
// ------------------------------------------------------------------------
|
||||||
if (path == null || path.isBlank()) return "";
|
// Outil interne : construit l’URL complète baseUrl + path + ?ws_key=...¶ms...
|
||||||
// /products -> products
|
// ------------------------------------------------------------------------
|
||||||
return path.startsWith("/") ? path.substring(1) : path;
|
private String buildUrl(String path, MultiValueMap<String, String> params) {
|
||||||
|
StringBuilder full = new StringBuilder();
|
||||||
|
|
||||||
|
// baseUrl
|
||||||
|
full.append(baseUrl);
|
||||||
|
|
||||||
|
// path
|
||||||
|
if (path != null && !path.isBlank()) {
|
||||||
|
boolean baseEndsWithSlash = baseUrl.endsWith("/");
|
||||||
|
boolean pathStartsWithSlash = path.startsWith("/");
|
||||||
|
|
||||||
|
if (baseEndsWithSlash && pathStartsWithSlash) {
|
||||||
|
full.append(path.substring(1));
|
||||||
|
} else if (!baseEndsWithSlash && !pathStartsWithSlash) {
|
||||||
|
full.append("/").append(path);
|
||||||
|
} else {
|
||||||
|
full.append(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ws_key en premier param
|
||||||
* Construit une URL complète Presta avec ws_key et params encodés UNE SEULE FOIS.
|
full.append("?ws_key=").append(URLEncoder.encode(apiKey, StandardCharsets.UTF_8));
|
||||||
* Utilisée par toutes les méthodes "admin" (getJson/getXml/postXml/putXml/delete).
|
|
||||||
*/
|
|
||||||
private String buildUrl(String path, MultiValueMap<String, String> params) {
|
|
||||||
StringBuilder fullUrl = new StringBuilder();
|
|
||||||
|
|
||||||
fullUrl.append(baseUrl)
|
|
||||||
.append("/")
|
|
||||||
.append(normalizePath(path));
|
|
||||||
|
|
||||||
// auth par ws_key (remplace Basic Auth)
|
|
||||||
String encodedKey = URLEncoder.encode(apiKey, StandardCharsets.UTF_8);
|
|
||||||
fullUrl.append("?ws_key=").append(encodedKey);
|
|
||||||
|
|
||||||
if (params != null && !params.isEmpty()) {
|
if (params != null && !params.isEmpty()) {
|
||||||
for (Map.Entry<String, List<String>> entry : params.entrySet()) {
|
for (Map.Entry<String, List<String>> entry : params.entrySet()) {
|
||||||
String name = entry.getKey();
|
String key = entry.getKey();
|
||||||
for (String value : entry.getValue()) {
|
for (String value : entry.getValue()) {
|
||||||
fullUrl.append("&")
|
full.append("&")
|
||||||
.append(URLEncoder.encode(name, StandardCharsets.UTF_8))
|
.append(URLEncoder.encode(key, StandardCharsets.UTF_8))
|
||||||
.append("=")
|
.append("=")
|
||||||
.append(URLEncoder.encode(value, StandardCharsets.UTF_8));
|
.append(URLEncoder.encode(value, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fullUrl.toString();
|
String url = full.toString();
|
||||||
|
log.debug("[PrestaShop] Built URL = {}", url);
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ------------------------------------------------------------------------
|
||||||
* Utilisé par le contrôleur proxy : on reçoit la query string brute
|
// GET JSON (utilisé partout dans PrestashopAdminService)
|
||||||
* (déjà encodée, ex: display=%5Bid,name,active%5D&output_format=JSON)
|
// ------------------------------------------------------------------------
|
||||||
* -> on NE LA RÉ-ENCODE PAS.
|
|
||||||
*/
|
|
||||||
public String getWithRawQuery(String resource, String rawQuery) {
|
|
||||||
StringBuilder fullUrl = new StringBuilder();
|
|
||||||
|
|
||||||
fullUrl.append(baseUrl)
|
|
||||||
.append("/")
|
|
||||||
.append(normalizePath(resource));
|
|
||||||
|
|
||||||
String encodedKey = URLEncoder.encode(apiKey, StandardCharsets.UTF_8);
|
|
||||||
fullUrl.append("?ws_key=").append(encodedKey);
|
|
||||||
|
|
||||||
if (rawQuery != null && !rawQuery.isBlank()) {
|
|
||||||
fullUrl.append("&").append(rawQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = fullUrl.toString();
|
|
||||||
log.info("[PrestaShop] RAW GET via ws_key = {}", url);
|
|
||||||
|
|
||||||
return client.get()
|
|
||||||
.uri(URI.create(url))
|
|
||||||
.accept(MediaType.APPLICATION_JSON, MediaType.ALL)
|
|
||||||
.retrieve()
|
|
||||||
.body(String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------
|
|
||||||
// GET JSON (utilisé PARTOUT dans PrestashopAdminService)
|
|
||||||
// -----------------------
|
|
||||||
|
|
||||||
public String getJson(String path, MultiValueMap<String, String> params) {
|
public String getJson(String path, MultiValueMap<String, String> params) {
|
||||||
String url = buildUrl(path, params);
|
String url = buildUrl(path, params);
|
||||||
log.info("[PrestaShop] GET JSON {}", url);
|
log.info("[PrestaShop] GET JSON {}", url);
|
||||||
|
|
||||||
return client.get()
|
return client.get()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
.accept(MediaType.APPLICATION_JSON, MediaType.ALL)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.body(String.class);
|
.body(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
// GET XML
|
// GET XML (utilisé pour certains appels de stock, produit, etc.)
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public String getXml(String path, MultiValueMap<String, String> params) {
|
public String getXml(String path, MultiValueMap<String, String> params) {
|
||||||
String url = buildUrl(path, params);
|
String url = buildUrl(path, params);
|
||||||
log.info("[PrestaShop] GET XML {}", url);
|
log.info("[PrestaShop] GET XML {}", url);
|
||||||
|
|
||||||
return client.get()
|
return client.get()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
.accept(MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.ALL)
|
.accept(MediaType.APPLICATION_XML)
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.body(String.class);
|
.body(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
// POST XML
|
// POST XML (création catégorie/produit/etc.)
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public String postXml(String path, MultiValueMap<String, String> params, String xmlBody) {
|
public String postXml(String path, MultiValueMap<String, String> params, String xmlBody) {
|
||||||
String url = buildUrl(path, params);
|
String url = buildUrl(path, params);
|
||||||
log.info("[PrestaShop] POST XML {}", url);
|
log.info("[PrestaShop] POST XML {} (body length={})", url, xmlBody != null ? xmlBody.length() : 0);
|
||||||
|
|
||||||
return client.post()
|
return client.post()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
.contentType(MediaType.APPLICATION_XML)
|
.contentType(MediaType.APPLICATION_XML)
|
||||||
.accept(MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.ALL)
|
.accept(MediaType.APPLICATION_XML)
|
||||||
.body(xmlBody)
|
.body(xmlBody != null ? xmlBody : "")
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.body(String.class);
|
.body(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
// PUT XML
|
// PUT XML (update catégorie/produit/stock/etc.)
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public String putXml(String path, MultiValueMap<String, String> params, String xmlBody) {
|
public String putXml(String path, MultiValueMap<String, String> params, String xmlBody) {
|
||||||
String url = buildUrl(path, params);
|
String url = buildUrl(path, params);
|
||||||
log.info("[PrestaShop] PUT XML {}", url);
|
log.info("[PrestaShop] PUT XML {} (body length={})", url, xmlBody != null ? xmlBody.length() : 0);
|
||||||
|
|
||||||
return client.put()
|
return client.put()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
.contentType(MediaType.APPLICATION_XML)
|
.contentType(MediaType.APPLICATION_XML)
|
||||||
.accept(MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.ALL)
|
.accept(MediaType.APPLICATION_XML)
|
||||||
.body(xmlBody)
|
.body(xmlBody != null ? xmlBody : "")
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.body(String.class);
|
.body(String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
// DELETE
|
// DELETE (suppression ressource)
|
||||||
// -----------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public void delete(String path, MultiValueMap<String, String> params) {
|
public void delete(String path, MultiValueMap<String, String> params) {
|
||||||
String url = buildUrl(path, params);
|
String url = buildUrl(path, params);
|
||||||
log.info("[PrestaShop] DELETE {}", url);
|
log.info("[PrestaShop] DELETE {}", url);
|
||||||
@@ -186,6 +154,43 @@ public class PrestashopClient {
|
|||||||
client.delete()
|
client.delete()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.body(Void.class);
|
.toBodilessEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Spécial proxy GET brut : on garde la query telle quelle (déjà encodée)
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
public String getWithRawQuery(String resource, String rawQuery) {
|
||||||
|
try {
|
||||||
|
StringBuilder fullUrl = new StringBuilder();
|
||||||
|
fullUrl.append(baseUrl);
|
||||||
|
// baseUrl : https://shop.gameovergne.fr/api
|
||||||
|
if (!baseUrl.endsWith("/")) {
|
||||||
|
fullUrl.append("/");
|
||||||
|
}
|
||||||
|
// resource : "categories", "products", ...
|
||||||
|
fullUrl.append(resource);
|
||||||
|
|
||||||
|
// ws_key
|
||||||
|
String encodedKey = URLEncoder.encode(apiKey, StandardCharsets.UTF_8);
|
||||||
|
fullUrl.append("?ws_key=").append(encodedKey);
|
||||||
|
|
||||||
|
// rawQuery = "display=%5Bid,name,active%5D&output_format=JSON"
|
||||||
|
if (rawQuery != null && !rawQuery.isBlank()) {
|
||||||
|
fullUrl.append("&").append(rawQuery); // surtout ne pas réencoder
|
||||||
|
}
|
||||||
|
|
||||||
|
String urlString = fullUrl.toString();
|
||||||
|
log.info("[PrestaShop] RAW GET via ws_key = {}", urlString);
|
||||||
|
|
||||||
|
return client.get()
|
||||||
|
.uri(URI.create(urlString))
|
||||||
|
.retrieve()
|
||||||
|
.body(String.class);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[PrestaShop] getWithRawQuery error for resource={} rawQuery={}", resource, rawQuery, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user