Программно сгенерированный продукт Woocommerce (плагин Wordpress) недоступен для гостей

Я использую WordPress 3.9.1 и последнюю версию WooCommerce (2.1.10) и пытаюсь создать страницу «Оплата счета», где люди указывают номер и сумму своего счета и сразу переходят на страницу оформления заказа.

Как я это делаю сейчас:

У меня есть страница с формой, где люди вводят сумму:

<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>

Кнопка отправки ведет на страницу, которая автоматически создает продукт Woocommerce на ту же сумму, добавляет его в корзину и автоматически перенаправляет на страницу оформления заказа (я использую плагин Insert PHP для всех моих потребностей 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]

Кажется, это работает отлично, пока я вошел в систему. Однако, если пользователь не вошел в систему, продукт все еще генерируется, но не может быть добавлен в корзину, показывая следующее сообщение: «К сожалению, этот продукт не может быть куплено». (что все портит).

Странно то, что любой другой продукт, который я создаю через интерфейс WooCommerce, может быть доступен гостям (поэтому, если у меня есть общедоступный продукт, и я программно меняю его цену и добавляю его в корзину, это работает -> но это создает проблемы когда 2 человека нажимают кнопку одновременно).

Прежде чем вы спросите, я включил гостевую проверку в настройках WooCommerce.

Любые идеи о том, как это исправить? (Или, возможно, совершенно другой способ достижения моей цели?)

Влад


person Vlad    schedule 06.06.2014    source источник


Ответы (4)


Я только что столкнулся с той же проблемой с составным продуктом.

Я решил это, работая в обратном направлении от сообщения об ошибке.

Я начал с того, что сделал в своем каталоге wp-content:

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

Примечание. ack очень похож на grep, но намного лучше.

Это вернуло следующие результаты (ваши результаты будут зависеть от установленных вами плагинов):

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' ),

Оттуда я заметил, что существует сопоставление woocommerce i18n с i18n_unavailable_text на мою исходную строку поиска.

Чтобы не пропустить никаких других событий, я старательно acked для:

$ ack i18n_unavailable_text

Это дало:

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' ),

Вооружившись этим списком, я запустил свой текстовый редактор и просмотрел два результата, которые я определил как релевантные:

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' );

Я поставил в браузере точку останова для js-файла, который, кстати, в моем случае пришлось переместить на место, потому что, естественно, браузер использовал минифицированную версию, без исходных карт. Эта точка останова не сработала, поэтому я перешел к сеансу отладки php. Это оказалось успешным и завело меня дальше в кроличью нору (извините за мои номера строк vim - я использую set relativenumber в vim, но соответствующие номера строк в plugins/woocommerce/includes/class-wc-cart.php - 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       }

Документация для: $product_data->is_purchasable()

Я использую kint для отладки, поэтому я добавил некоторые отладочные данные на основе инструкции if в документации. выше, чтобы увидеть, что не прошло проверку на возможность покупки:

   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       }

Это сообщило мне, что $product_data->post->post_status !== 'publish' bool FALSE. Это, конечно, означало, что почему-то мой пост не был опубликован. Это привело к еще одной более низкой ступени вниз в кроличью нору, когда я запустил этот sql-запрос (10962 был идентификатором продукта/сообщения-виновника, а wp_4_posts — это имя таблицы для моей таблицы сообщений на сетевом сайте WordPress, где это сообщение находилось:

SELECT post_status FROM wp_4_posts WHERE id = '10962'

Это вернуло post_status: publish. Кто-нибудь, пристрелите меня сейчас, была моя непосредственная реакция. Но я также заметил:

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

Таким образом, цена была рассчитана неправильно для этого продукта.

Снова вернемся к документации, на этот раз для $product_data-> получить_цену()

Подумав об этом несколько минут, я быстро понял, что не добавил к продукту базовую цену, думая, что, указав «цену за единицу товара», мне не нужно будет устанавливать базовую цену. Горе было мне. Оказалось, что это очень хорошо описано в документации по составным продуктам:

составная документация по ценам на товары

person zealoushacker    schedule 15.08.2015

Я видел эту проблему раньше. В рассматриваемом продукте отсутствовала часть метаданных поста. Сравните свою таблицу post_meta после добавления продукта, затем отредактируйте продукт, сохраните его и снова сравните таблицу. Проверьте, какие ключи добавил WooCommerce.

Требуется строгий отбор мета-ключей, чтобы вы могли приобрести продукт.

SELECT * FROM wp_postmeta WHERE post_id = '1234567' ORDER BY 'meta_key'

person Senrab    schedule 31.07.2014
comment
Ничего себе, не ожидал ответа; спасибо Кирану «Кизбо» Барнсу. Я решил проблему, создав вручную ~ 50 продуктов (поэтому доступных для пользователя). Всякий раз, когда пользователь создает новый счет-фактуру (вводит значение в текстовое поле и нажимает «ОК»), один из продуктов выбирается случайным образом, и его цена изменяется на введенное значение. Таким образом, у пользователя есть доступ к продукту, и он не испортится, если несколько человек одновременно нажмут кнопку «ОК». - person Vlad; 01.08.2014

Я только что столкнулся с похожей проблемой, и я хотел поделиться тем, что я сделал, чтобы решить свою проблему. Сначала немного контекста: я хотел, чтобы пользователи могли покупать объявления (например, Craigslist) на сайте с переменной ценой в зависимости от выбранных вами опций и длины объявления. Поэтому, естественно, я не мог создавать фиксированные продукты, которые люди могли бы просто купить. Эти добавления должны были быть опубликованы позже (из-за того, что они были связаны с бумажной версией газеты), поэтому добавления будут созданы со статусом «будущее», а WordPress будет отображать их как «опубликовать» по мере достижения даты.

Все работало нормально, когда я входил в систему как администратор, но когда я входил в систему как обычный пользователь, люди не могли покупать добавки, появлялась ошибка «извините, этот продукт нельзя купить». Я сделал то, что многие вообще не рекомендовали бы (даже я сам), но это было единственное решение, которое я нашел за ограниченное время.

Woocommerce проверяет эти вещи в следующем порядке, чтобы узнать, можно ли купить продукт:

продукт существует продукт имеет цену (postmeta _price != "") продукт находится в статусе "опубликовать" ИЛИ текущий пользователь может редактировать продукт (например, администратор)

Я добавил проверку к этому последнему, чтобы разрешить покупку продукта, если текущий пользователь является автором продукта (таким образом, человек, создающий добавление, сможет его купить, но никто другой).

Итак, в файле woocommerce/includes/abstracts/abstract-wc-product.php (из вашего каталога плагинов) в строке 690 у вас есть это

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

изменил его на

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

Я не рекомендую этого, если вы можете избежать этого, поскольку у него есть недостаток, заключающийся в том, что при обновлении woocommerce он может повторно загрузить этот файл, и изменение может быть потеряно. Но если это ваше единственное решение, как это было для меня (в основном из-за нехватки времени и отсутствия слишком больших задумок), что ж...

person Victor D.    schedule 28.11.2014

Как и в моем комментарии выше, способ решить эту проблему:

Я решил проблему, создав вручную ~ 50 продуктов (поэтому доступных для пользователя). Всякий раз, когда пользователь создает новый счет-фактуру (вводит значение в текстовое поле и нажимает «ОК»), один из продуктов выбирается случайным образом, и его цена изменяется на введенное значение. Таким образом, у пользователя есть доступ к продукту, и он не испортится, если несколько человек одновременно нажмут кнопку «ОК».

person Vlad    schedule 01.02.2017