package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.rest.client.HelloAssoAuthClient; import fr.titionfire.ffsaf.rest.client.dto.TokenResponse; import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.jboss.logging.Logger; @ApplicationScoped public class HelloAssoTokenService { private static final Logger LOG = Logger.getLogger(HelloAssoTokenService.class); @Inject @RestClient HelloAssoAuthClient authClient; @ConfigProperty(name = "helloasso.client-id") String clientId; @ConfigProperty(name = "helloasso.client-secret") String clientSecret; private TokenResponse currentToken; // Stockage en mémoire (pour un seul pod) // Récupère un token valide (en le rafraîchissant si nécessaire) public Uni getValidAccessToken() { if (currentToken == null || currentToken.isExpired()) { return fetchNewToken(clientId, clientSecret); } return Uni.createFrom().item(currentToken.accessToken); } // Récupère un nouveau token (via client_credentials ou refresh_token) private Uni fetchNewToken(String clientId, String clientSecret) { if (currentToken != null && currentToken.refreshToken != null) { // On utilise le refresh_token si disponible return authClient.refreshToken("refresh_token", clientId, currentToken.refreshToken) .onItem().invoke(token -> { LOG.info("Token rafraîchi avec succès"); currentToken = token; }) .onFailure().recoverWithItem(e -> { LOG.warn("Échec du rafraîchissement, utilisation des credentials", e); return null; // Force l'utilisation des credentials }) .flatMap(token -> token != null ? Uni.createFrom().item(token.accessToken) : getTokenWithCredentials(clientId, clientSecret) ); } else { return getTokenWithCredentials(clientId, clientSecret); } } // Récupère un token avec client_id/client_secret private Uni getTokenWithCredentials(String clientId, String clientSecret) { return authClient.getToken("client_credentials", clientId, clientSecret) .onItem().invoke(token -> { LOG.info("Nouveau token obtenu"); currentToken = token; }) .onFailure().invoke(e -> LOG.error("Erreur lors de l'obtention du token", e)) .map(token -> token.accessToken); } }