Obtention d'une exception «Veuillez spécifier une méthode d'expédition» lors du paiement

18

J'ai reçu des journaux d'exceptions pour cette erreur de production, mais je ne parviens pas à reproduire le problème dans mon environnement local ou intermédiaire, il a donc été assez difficile à résoudre.

L'erreur provient du Mage_Sales_Model_Service_Quote::_validate()fait que le $rateretourné par $rate = $address->getShippingRateByCode($method)est vide.

J'ai ajouté de la journalisation pour essayer d'avoir une meilleure idée de ce qui se passait, et je peux voir que $methodcontient la bonne méthode d'expédition.

Ma meilleure supposition est qu'à un moment donné du processus, les tarifs d'expédition sont supprimés avant le moment où ils devraient l'être.

J'ai remarqué que chaque fois que cette exception se produit, elle se produit immédiatement après une exception légitime, telle qu'une carte de crédit invalide. J'ai essayé de reproduire le problème en utilisant une carte de crédit non valide, puis une carte valide, mais elle ne se reproduit pas pour moi - en mise en scène, en production ou en local.

Mon intuition initiale était que la méthode d'expédition se perdait peut-être quelque part après la première exception valide, mais ce n'est pas le cas, car je vois que cela $methoda la bonne valeur au moment où cette exception est levée.

Le module de paiement que j'utilise est AwesomeCheckout - il n'a pas vraiment à ma connaissance de logique personnalisée lors de la création de commandes qui devrait causer des problèmes ici, mais pourrait être lié.

MISE À JOUR: J'ai ajouté du code pour tenter de récupérer les tarifs s'ils sont manquants.

protected function _validate()
{
    if (!$this->getQuote()->isVirtual()) {
        $address = $this->getQuote()->getShippingAddress();
        $addressValidation = $address->validate();
        if ($addressValidation !== true) {
            Mage::throwException(
                Mage::helper('sales')->__('Please check shipping address information. %s', implode(' ', $addressValidation))
            );
        }
        $method= $address->getShippingMethod();
        $rate  = $address->getShippingRateByCode($method);

        /**
         * Start Customization
         */
        if (!$this->getQuote()->isVirtual() && !$rate) {
            Mage::logException(new Exception("Rate was empty inside quote validate method, trying to forcefully recalculate"));
            $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
            $this->getQuote()->setTotalsCollectedFlag(false);
            $this->getQuote()->collectTotals();
            $rate  = $address->getShippingRateByCode($method);
        }
        /** End Customization **/             

        if (!$this->getQuote()->isVirtual() && (!$method || !$rate)) {
            Mage::throwException(Mage::helper('sales')->__('Please specify a shipping method.'));
        }
    }
kalenjordan
la source
Utilisez-vous une extension d'expédition tierce? Tester avec une méthode Magento native comme flatrate donnerait peut-être un aperçu, que ce soit l'extension de paiement ou l'extension d'expédition
Sander Mangel
1
J'ai également vu un magasin avec cela se produire en production, souvent plusieurs fois de suite. Nous n'avons jamais pu nous reproduire dans aucun environnement.
Peter O'Callaghan
@Sander, Oui, nous utilisons une extension tierce. Je suis à peu près sûr que ce n'est pas la cause principale, car elle retourne très bien les taux sur la méthode collectRates () et même dans les cas où cela échoue, je peux voir que les taux ont été très bien retournés sur l'API.
kalenjordan
@Cags, vraiment ??! Bon à savoir, nous devrons peut-être étiqueter cette équipe. C'est une de ces choses qui est importante mais parce qu'elle se reproduit très rarement, ce n'est pas une priorité majeure.
kalenjordan
@SanderMangel, malheureusement, essayer ceci avec un taux forfaitaire n'est pas une option, car nous ne pouvons pas simplement arrêter de servir les tarifs d'expédition corrects à des centaines de clients en production afin d'essayer de reproduire le problème. Si je pouvais reproduire cela dans mon environnement local, il est certain que tester avec une méthode d'expédition à la vanille serait l'une des premières choses que j'essaierais.
kalenjordan

Réponses:

8

Vous devez comprendre comment fonctionnent les tarifs et comment ils sont demandés. Fondamentalement, les taux sont demandés lorsque ->setCollectShippingRates(true)est défini sur l'objet shippinAddress et que les taux sont collectés et stockés dans la table des taux. Ce tableau est ensuite vidé et rempli à nouveau sur nouvelle demande de tarif.

ce qui se passe dans votre cas, c'est qu'une erreur est lancée et que la demande est répétée et que les tarifs ne sont pas demandés mais devraient être là. Alors essayez de forcer la collecte des tarifs

getQuote()->getShippingAddress()->setCollectShippingRates(true);

puis essayez de récupérer les totaux aussi si cela ne fonctionne pas

getQuote()->setTotalsCollectedFlag(false)->collectTotals();

soyez averti que l'appel de collectTotals plusieurs fois peut perturber vos totaux si une extension n'implémente pas correctement les objets de totaux (une faille commune)

Anton S
la source
Merci, c'est logique. Une idée pourquoi cela se produirait si rarement? Si l'erreur de paiement réinitialisait les tarifs, je m'attendrais à ce que cela se produise chaque fois qu'il y a une erreur de paiement.
kalenjordan
cela dépend des drapeaux et s'il est appelé ou non si vous pouvez le répliquer en cas d'erreur, il est facile de tracer avec le débogueur. Cependant, si votre erreur de méthode de paiement ne fait pas un aller-retour complet vers le serveur et casse simplement la demande avec sortie, elle peut simplement interrompre l'exécution de tous les observateurs dépendants, etc.
Anton S
Ajouté dans du code et il a toujours échoué. J'ai oublié la $this->getQuote()->getShippingAddress()->setCollectShippingRates(true)ligne, donc je vais essayer maintenant.
kalenjordan
Le problème est réapparu et le code que j'ai en place a empêché l'exception de se produire. Mais la transaction a toujours échoué car SIMULTANEOUSLY braintree a été indisponible pendant quelques minutes. Incroyable.
kalenjordan
1
D'accord, grattez ça. La raison pour laquelle cela s'est produit cette fois était pour des raisons entièrement différentes. Une commande d'abonnement tentait d'être générée pour une adresse où aucun tarif de livraison n'était réellement disponible, le message d'erreur était donc valide. @ProxiBlue
kalenjordan
3

Pourrait avoir compris cela. J'ai eu une exception connexe qui était lancée avec à peu près la même fréquence que celle-ci, qui était "La méthode de paiement demandée n'est pas disponible".

Il s'avère que la raison pour laquelle cela se produisait était parce que l'un de mes observateurs était en train de sales_place_order_aftercréer un objet de devis (et de l'enregistrer) afin de générer des prix d'abonnement.

J'ai pu le faire reproduire en vérifiant d'abord avec une mauvaise carte de crédit en tant que nouveau client (non connecté), puis en revenant et en corrigeant la carte de crédit et en essayant à nouveau de commander.

L'exception a été levée car, dans l' loadCustomerQuoteobservateur de customer_login, il fusionnera vos devis si vous avez plusieurs devis, et ce faisant, il perd certaines informations sur le mode de paiement sur le devis.

Le correctif consistait à supprimer le nouveau devis que je créais dans mon observateur d'abonnement.

MISE À JOUR: Non, le correctif pour "La méthode de paiement demandée n'est pas disponible" n'a pas résolu ce problème, toujours en cours.

kalenjordan
la source
Assez tard, mais c'est pourquoi je n'utilise plus du tout cet événement (passer la commande après). Si j'ai besoin que quelque chose se passe après une commande, je vais dans une file d'attente.
philwinkle
De la même manière, vous m'aiderez
zus
0

Il suffit de noter que PayPal Express donne parfois une erreur indiquant "Payeur non identifié" lors de la commande. Cette erreur provient de la même exception "Veuillez spécifier une méthode d'expédition". Dans Magento 1.8.1.0, cela est facilement reproductible en provoquant une "fusion de devis" ou une "fusion de panier" lors de la commande. La fusion des devis ou des paniers entraînera la suppression des tarifs d'expédition mais non leur recalcul. Et en fait, vous ne voulez pas résoudre ce problème, car alors le client pourrait payer plus que ce qu'il avait convenu! Au lieu de cela, vous souhaiterez supprimer la fonctionnalité de fusion - ou mettre à niveau Magento.

Ceci est corrigé dans 1.9; les clients doivent d'abord se connecter avant d'être redirigés vers PayPal.

Erfan
la source
0

Dans mon cas, cette erreur provient de la nullvaleur dans $methodet$rate

$method= $address->getShippingMethod();
$rate  = $address->getShippingRateByCode($method);
    if (!$this->getQuote()->isVirtual() && (!$method || !$rate)) {
Mage::throwException(Mage::helper('sales')->__('Please specify a 
shipping method.'));
}

j'ai donc mis un taux à partir de cela. dans la méthode et le taux disponibles dans votre magento

$quote = Mage::getSingleton('checkout/session')->getQuote();
$address = $quote->getShippingAddress();
$shippingMethod = 'amtable_amtable5';
$shippingMethod = 'flatrate_flatrate';
$address->setCollectShippingRates(true)->collectShippingRates()->setShippingMethod($shippingMethod);
May Noppadol
la source