Le produit généré par programme Woocommerce (plugin WordPress) n’est pas accessible aux invités
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).
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 …
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-content
répertoire :
$ ack "Sorry, this product cannot be purchased."
Remarque : ack
ressemble 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_text
de ma chaîne de recherche d’origine.
Afin de ne manquer aucune autre occurrence, j’ai rédigé avec diligence ack
pour :
$ 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 relativenumber
dans vim – mais les numéros de ligne pertinents plugins/woocommerce/includes/class-wc-cart.php
sont 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()
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_posts
est 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 :
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.
0 commentaire