# Pourquoi wc_price() affiche un montant faux après un changement de devise

> Changer de devise en cours de navigation fait parfois apparaître un prix qui ne correspond plus à rien. Le coupable est presque toujours un cache de fragment mal invalidé.

- Auteur : Clément Hadrot
- Publié le : 2025-07-15
- Mis à jour le : 2025-07-15
- Catégorie : E-commerce
- URL : https://wpmoderne.dev.wordpress-developpement.fr/ecommerce/wc-price-montant-faux-changement-devise/

## L’essentiel

- Le symbole change mais pas le montant
- Le cache de fragment est le suspect numéro un
- Un filtre suffit à corriger l'affichage

« J'ai changé la devise en haut de page et le prix affiché ne bouge plus, ou pire, il affiche un montant absurde. » C'est le message reçu d'un client international qui teste un sélecteur multidevise fraîchement installé sur une boutique WooCommerce. Le symbole monétaire change bien, mais la valeur numérique reste celle de la devise précédente, ou se retrouve multipliée par un taux appliqué deux fois.

Ce bug touche presque toujours les boutiques qui combinent une extension de conversion de devise avec un système de cache de fragments, deux briques qui ne se parlent pas naturellement.

## Symptôme : un prix cohérent au premier chargement, faux ensuite

Le scénario typique se déroule en trois temps. Le visiteur arrive sur la fiche produit, le prix s'affiche correctement dans la devise par défaut. Il change de devise via le sélecteur, une requête AJAX recalcule le taux et devrait rafraîchir l'affichage. Mais le fragment HTML contenant le prix, généré par `wc_price()`, reste identique à celui servi par le cache de page ou par le cache de fragments, sans que le nouveau taux de conversion soit pris en compte dans la valeur numérique affichée.

Le fait que le symbole change parfois seul, sans la valeur, confirme le diagnostic : un morceau de gabarit dépendant de la devise sélectionnée (souvent le symbole, injecté côté client) se met à jour via JavaScript, tandis que le montant lui-même, calculé côté serveur par `wc_price()` et mis en cache dans le HTML, reste figé sur son ancienne valeur.

## Diagnostic : la fonction wc_price() n'est pas coupable, son contexte l'est

`wc_price()` ne fait qu'appliquer un formatage à un nombre qu'on lui donne : séparateur décimal, position du symbole, nombre de décimales selon les réglages WooCommerce. Le bug ne vient donc jamais de cette fonction elle-même mais de ce qui l'entoure : soit le montant transmis n'a pas été reconverti au bon taux, soit le fragment HTML qui contient l'appel à `wc_price()` a été mis en cache avant que le filtre de conversion ne s'applique.

Pour confirmer, on isole le problème avec un test direct dans la console de débogage WordPress ou via WP-CLI :

```
wp eval 'echo wc_price( 42, array( "currency" => "USD" ) );'
```

Si ce test isolé renvoie le bon montant converti mais que la page affichée reste fausse, le problème n'est pas dans la logique de conversion elle-même mais bien dans une couche de cache placée entre le calcul et l'affichage : cache de page complet, cache de fragment sur le bloc prix, ou objet de transient WooCommerce qui stocke le prix calculé sans tenir compte de la devise de session.

> L'essentiel à retenir : Le symbole change mais pas le montant ; Le cache de fragment est le suspect numéro un ; Un filtre suffit à corriger l'affichage

## Correctif : reconvertir au bon moment, invalider au bon endroit

La correction la plus fiable consiste à accrocher un filtre sur `woocommerce_get_price_html`, qui s'exécute au moment de l'affichage, plutôt que de modifier le prix stocké en base, qui doit rester dans la devise de référence de la boutique :

```
add_filter( 'woocommerce_get_price_html', function( $prix_html, $produit ) {
    $devise = ma_devise_de_session();
    $taux   = ma_fonction_taux( $devise );
    $prix_converti = (float) $produit->get_price() * $taux;

    return wc_price( $prix_converti, array( 'currency' => $devise ) );
}, 20, 2 );
```

Ce filtre garantit que le calcul de conversion se fait à chaque affichage, avec la devise de session courante, sans dépendre d'un montant précalculé et potentiellement mis en cache. Reste à traiter le cache lui-même : si la boutique utilise un cache de fragment sur le bloc contenant le prix, ce fragment doit varier selon la devise sélectionnée, en incluant cette devise dans la clé de cache, faute de quoi deux visiteurs avec des devises différentes se partageront le même fragment mis en cache.

### Cas particulier du panier et des blocs Interactivity API

Sur le panier et le tunnel de commande construits avec les blocs Interactivity API, le prix affiché transite par la Store API plutôt que par un gabarit PHP classique. Le même principe s'applique : le montant renvoyé par `/wc/store/v1/cart` doit refléter la devise de session au moment de la requête, ce qui suppose que le filtre de conversion s'accroche également sur les données exposées par cette API, et non uniquement sur l'affichage côté gabarit.

## Prévention : tester le changement de devise en cours de session, pas seulement au chargement

La plupart des recettes de boutiques multidevises se limitent à vérifier que la bonne devise s'affiche au chargement initial de chaque page, selon la géolocalisation ou la préférence enregistrée. Ce test ne suffit pas : il faut systématiquement rejouer le scénario du changement de devise en cours de navigation, sur une fiche produit déjà en cache, pour vérifier que le montant affiché change réellement et pas seulement son symbole.

- Vérifier le comportement sur une page déjà servie par le cache avant le changement de devise.
- Vérifier le panier après ajout d'un produit dans une devise puis changement vers une autre.
- Vérifier que la clé de cache de fragment inclut bien la devise sélectionnée.

## En résumé

Un montant faux après un changement de devise n'est presque jamais un problème de calcul dans `wc_price()`, mais un problème de moment : le prix a été mis en cache avant que la conversion ne s'applique, ou la clé de cache ignore la devise sélectionnée. Accrocher la conversion sur `woocommerce_get_price_html` et faire varier les clés de cache selon la devise résout durablement ce type d'incohérence.
