Le produit généré par programme Woocommerce (plugin WordPress) n’est pas accessible aux invités

Publié par Jean-Michel le

J’utilise WordPress 3.9.1 et la dernière version de WooCommerce (2.1.10) et j’essaie de créer une page « Payer votre facture » où les gens mettent leur numéro de facture et leur montant et ils vont directement à la page de paiement.

La façon dont je le fais maintenant:

J’ai une page avec un formulaire où les gens inscrivent le montant :

<form action="#" onsubmit="location.href = 'http://protexfs.co/invoicepage/?date=' + this.elements.date.value; return false;">
<input type="text" name="date">
<input type="submit" value="Go">
</form>

Le bouton Soumettre mène à une page qui génère automatiquement un produit Woocommerce pour le même montant et l’ajoute au panier et redirige automatiquement vers la page de paiement (j’utilise le plugin Insert PHP pour tous mes besoins PHP) :

[insert_php]
//empty cart
global $woocommerce;
$woocommerce->cart->empty_cart();
// Remove default cart message
$woocommerce->clear_messages();

//price
$invoiceprice = filter_input(INPUT_GET,"date",FILTER_SANITIZE_STRING);

//Generate title
$timestampedtitle = "Date: ".date("d/m/Y")." Amount: £".$invoiceprice;

//Generate message
$message = date_timestamp_get(date_create())." Date: ".date('m/d/Y h:i:s a', time())." Invoice amount: £".$invoiceprice;

$post = array(
'post_author' => '2',
'post_status' => "publish",
'post_title' => $timestampedtitle,
'post_content' => $message,
'post_parent' => '',
'post_type' => "product",
//'post_status' => 'private',
);

//Create post
$post_id = wp_insert_post( $post, $wp_error );
if($post_id){
$attach_id = get_post_meta($product->parent_id, "_thumbnail_id", true);
add_post_meta($post_id, '_thumbnail_id', $attach_id);
}
wp_set_object_terms($post_id, 'simple', 'product_type');
update_post_meta( $post_id, '_visibility', 'search' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, '_virtual', 'yes');
update_post_meta( $post_id, '_regular_price', $invoiceprice );
update_post_meta( $post_id, '_sale_price', $invoiceprice );
update_post_meta( $post_id, '_purchase_note', "" );
update_post_meta( $post_id, '_featured', "no" );
update_post_meta( $post_id, '_weight', "" );
update_post_meta( $post_id, '_length', "" );
update_post_meta( $post_id, '_width', "" );
update_post_meta( $post_id, '_height', "" );
update_post_meta($post_id, '_sku', "");
update_post_meta( $post_id, '_product_attributes', array());
update_post_meta( $post_id, '_sale_price_dates_from', "" );
update_post_meta( $post_id, '_sale_price_dates_to', "" );
update_post_meta( $post_id, '_price', $invoiceprice );
update_post_meta( $post_id, '_sold_individually', "" );
update_post_meta( $post_id, '_manage_stock', "no" );
update_post_meta( $post_id, '_backorders', "no" );
update_post_meta( $post_id, '_stock', "" );
update_post_meta( $post_id, '_et_pb_page_layout', 'et_full_width_page' );

if( $woocommerce->cart ) {
     $woocommerce->cart->add_to_cart( $post_id, $quantity=1 );}

$url = $woocommerce->cart->get_checkout_url();
header("Location: $url");
[/insert_php]

Cela semble fonctionner parfaitement tant que je suis connecté. Cependant, si l’utilisateur n’est pas connecté, le produit est toujours généré mais ne peut pas être ajouté au panier, affichant le message suivant : « Désolé, ce produit ne peut pas être acheté. » (ce qui gâche tout).

Ce qui est étrange, c’est que tout autre produit que je crée via l’interface WooCommerce est accessible aux invités (donc si j’ai un produit accessible au public et que je modifie son prix par programme et que je l’ajoute au panier, cela fonctionne -> mais cela crée des problèmes lorsque 2 personnes cliquent sur le bouton en même temps).

Lire également:  Wordpress : Comment supprimer l'image d'en-tête/titre de page dans le thème Farvis ?

Avant que vous ne le demandiez, j’ai activé le paiement en tant qu’invité dans le paramètre WooCommerce.

Des idées pour résoudre le problème? (Ou peut-être une manière complètement différente d’atteindre mon objectif ?)

Vlad

Solution n°1 trouvée

Je viens de rencontrer un problème similaire et je voulais partager ce que j’ai fait pour résoudre mon problème. Un peu de contexte d’abord, je voulais que les utilisateurs puissent acheter des annonces (pensez comme craigslist) sur le site qui avaient un prix variable en fonction des options que vous avez sélectionnées et de la durée de l’annonce. Donc, naturellement, je ne pouvais pas créer de produits fixes que les gens pouvaient simplement acheter. Ces annonces devaient être publiées à une date ultérieure (car elles étaient liées à une version papier d’un journal) donc les annonces seront créées avec le statut « futur » et wordpress les rendra « publiées » lorsque la date sera atteinte.

Tout fonctionnait bien lorsque j’étais connecté en tant qu’administrateur, mais lorsque je me connectais en tant qu’utilisateur régulier, les gens ne pouvaient pas acheter les annonces, l’erreur « désolé, ce produit ne peut pas être acheté » s’affichait. Ce que j’ai fait est ce que beaucoup ne recommanderaient pas du tout (même moi-même), mais c’était la seule solution que j’ai trouvée pour le temps limité.

Woocommerce vérifie ces choses, dans cet ordre pour savoir si un produit est achetable :

le produit existe le produit a un prix (postmeta _price != «  ») le produit est en statut « publier » OU l’utilisateur actuel peut modifier le produit (alias un administrateur par exemple)

J’ai ajouté la vérification à cette dernière pour permettre l’achat d’un produit si l’utilisateur actuel est l’auteur du produit (ainsi la personne créant l’ajout pourra l’acheter, mais personne d’autre).

Donc sur le fichier woocommerce/includes/abstracts/abstract-wc-product.php (de votre répertoire de plugins) sur la ligne 690 vous avez ceci

elseif ( $this->post->post_status !== 'publish' && ! current_user_can( 'edit_post', $this->id )

changé en

elseif ( $this->post->post_status !== 'publish' && ! current_user_can( 'edit_post', $this->id ) && $this->post->post_author != get_current_user_id()) {

Je ne le recommande pas si vous pouvez l’éviter car il présente l’inconvénient que si woocommerce est mis à jour, il peut retélécharger ce fichier et la modification peut être perdue. Mais si c’est votre seule solution comme c’était le cas pour moi (principalement en raison de contraintes de temps et de ne pas trop anticiper), eh bien …

Lire également:  Wordpress : Noms de catégories sur les pages d'archives CPT

Solution n°2 trouvée

Je viens de rencontrer le même problème avec un produit composite.

La façon dont je l’ai résolu est de travailler à rebours à partir du message d’erreur.

J’ai commencé par faire dans mon wp-contentrépertoire :

$ ack "Sorry, this product cannot be purchased."

Remarque : ackressemble beaucoup à grep, mais en bien mieux.

Cela a renvoyé les résultats suivants (vos résultats varieront selon les plugins que vous avez installés):

plugins/woocommerce/includes/class-wc-cart.php
825:                wc_add_notice( __( 'Sorry, this product cannot be purchased.', 'woocommerce' ), 'error' );

plugins/woocommerce-composite-products/includes/class-wc-cp-display.php
118:            'i18n_unavailable_text'                    => __( 'Sorry, this product cannot be purchased at the moment.', 'woocommerce-composite-products' ),

À partir de là, j’ai remarqué qu’il y avait un mappage woocommerce i18n à partir i18n_unavailable_textde ma chaîne de recherche d’origine.

Afin de ne manquer aucune autre occurrence, j’ai rédigé avec diligence ackpour :

$ ack i18n_unavailable_text

Cela a donné :

plugins/woocommerce/assets/js/frontend/add-to-cart-variation.js
392:                    $variation_form.find( '.single_variation' ).html( '<p>' + wc_add_to_cart_variation_params.i18n_unavailable_text + '</p>' );

plugins/woocommerce/includes/class-wc-frontend-scripts.php
197:                'i18n_unavailable_text'            => esc_attr__( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ),

plugins/woocommerce-composite-products/assets/js/add-to-cart-composite.js
2948:                       composite.disable_add_to_cart( wc_composite_params.i18n_unavailable_text );

plugins/woocommerce-composite-products/includes/class-wc-cp-display.php
118:            'i18n_unavailable_text'                    => __( 'Sorry, this product cannot be purchased at the moment.', 'woocommerce-composite-products' ),

Armé de cette liste, j’ai lancé mon éditeur de texte et j’ai examiné les deux résultats que j’ai identifiés comme pertinents :

plugins/woocommerce-composite-products/assets/js/add-to-cart-composite.js
2948:                       composite.disable_add_to_cart( wc_composite_params.i18n_unavailable_text );
plugins/woocommerce/includes/class-wc-cart.php
825:                wc_add_notice( __( 'Sorry, this product cannot be purchased.', 'woocommerce' ), 'error' );

J’ai mis un point d’arrêt dans mon navigateur pour le fichier js, que j’ai d’ailleurs dû mettre en place dans mon cas, car bien sûr le navigateur utilisait la version minifiée, sans sourcemaps. Ce point d’arrêt n’a pas été atteint, je suis donc passé à la session de débogage php. Cela a réussi et m’a conduit plus loin dans le terrier du lapin (pardonnez mes numéros de ligne vim – que j’utilise set relativenumberdans vim – mais les numéros de ligne pertinents plugins/woocommerce/includes/class-wc-cart.phpsont 824-825):

   2       // Check product is_purchasable
   1       if ( ! $product_data->is_purchasable() ) {
825          wc_add_notice( __( 'Sorry, this product cannot be purchased.', 'woocommerce' ), 'error' );
   1         return false;
   2       }

Documentation pour : $product_data->is_purchasable()

Lire également:  Wordpress : Remplacement du thème parent de la fonction dans le thème enfant

J’utilise kint pour le débogage, j’ai donc ajouté une sortie de débogage, basée sur l’instruction if de la documentation ci-dessus pour voir ce qui échouait aux vérifications de la possibilité d’achat :

   2       // Check product is_purchasable
   1       if ( ! $product_data->is_purchasable() ) {
825          d(! $product_data->exists());
   1         d($product_data->get_price() === '');
   2         d($product_data->post->post_status !== 'publish');
   3         d(! current_user_can( 'edit_post', $product_data->id ));
   4         wc_add_notice( __( 'Sorry, this product cannot be purchased.', 'woocommerce' ), 'error' );
   5         return false;
   6       }

Cela m’a informé que $product_data->post->post_status !== 'publish' bool FALSE. Cela signifiait bien sûr que, d’une manière ou d’une autre, mon message n’avait pas été publié. Cela a conduit à un autre échelon inférieur dans le terrier du lapin, lorsque j’ai exécuté cette requête sql ( 10962était l’identifiant du produit/poste coupable et wp_4_postsest le nom de la table de la table des messages de mon site de réseau wordpress, où ce message vivait :

SELECT post_status FROM wp_4_posts WHERE id = '10962'

C’est revenu post_status: publish. Que quelqu’un me tire dessus maintenant a été ma réaction immédiate. Mais, j’ai aussi remarqué :

$product_data->get_price() === '' bool FALSE

Le prix n’a donc pas été calculé correctement pour ce produit.

Revenons à la documentation, cette fois pour $product_data->get_price()

Après y avoir réfléchi quelques minutes, cela m’a amené à me rendre compte rapidement que je n’avais pas ajouté de prix de base au produit, pensant qu’ayant spécifié « Per-Item-Pricing », je n’aurais pas à fixer un prix de base. Malheur à moi. Il s’est avéré que cela était très bien documenté dans la documentation des produits composites :

documentation sur les prix des produits composites par article

Solution n°3 trouvée

Comme dans mon commentaire ci-dessus, la façon de résoudre ce problème est la suivante :

La façon dont j’ai résolu le problème était de créer manuellement ~ 50 produits (donc accessibles à l’utilisateur). Chaque fois que l’utilisateur crée une nouvelle facture (met une valeur dans le champ de texte et appuie sur ok), l’un des produits est choisi au hasard et son prix est modifié à la valeur saisie. De cette façon, l’utilisateur a accès au produit et il n’y a pas de problème si plusieurs personnes cliquent sur le bouton « Ok » en même temps.

Catégories : Wordpress

Jean-Michel

Jean-Michel est en charge de la partie blog du site. Il met en place la stratégie de contenu et répond aux questions fréquentes sur Wordpress.

0 commentaire

Laisser un commentaire

Avatar placeholder

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *