I am working on a website running WordPress and woocommerce
I have a custom function to add stuff to the cart which is the following:
function custom_add_products_to_cart(){
WC()->cart->empty_cart();
$request_body = file_get_contents('php://input');
$decoded = json_decode($request_body);
$cartElements = $decoded->addToCart;
foreach ( $cartElements as $product_id ) {
WC()->cart->add_to_cart( $product_id );
}
if ( $decoded->Uid ) {
WC()->session->set( 'uid', $decoded->Uid );
}
die();
};
This is quite a straightforward function. All it does is iterating through a list of products id and launching the default Woocommerce add to cart function.
The issue I've got is that this works perfectly fine on my localhost (also debugging it ut behaves just like expected) but when I try it on a test server it doesn't work.
The function is firing (i tried to print some messages) but the cart is not emptying and the new products are not added.
I check the code, commit and revision, and everything is correct.
What else can it be?
My last thought was on the version of PHP:
my localhost runs 7.1.2 while the test server runs 7.0.22 - can it be the PHP version or not? any idea on what else I could try?
Sorry if I cannot provide much more details but unfortunately there's not much more to add...
Also, I am not posting this to WordPress community for now as I think it's not a WordPress related stuff (nor woocommerce) but rather PHP code (maybe my function is somehow wrong?) or PHP version
Thanks in advance to everyone
i think the problem is here
file_get_contents('php://input');
depending on your PHP configuration, maybe you need to change the allow_url_fopen setting in you php.ini.
You have two ways of getting around it without changing php.ini, one of them is to use fsockopen(), and the other is to use cURL.
I recommend using cURL over file_get_contents() anyways, since it was built for this.
At the end i simply solve this by calling two functions:
the first one empties the cart:
function empty_cart(){
WC()->cart->empty_cart();
}
and the second one carries on adding to the cart:
function custom_add_products_to_cart(){
$request_body = file_get_contents('php://input');
$decoded = json_decode($request_body);
$cartElements = $decoded->addToCart;
foreach ( $cartElements as $product_id ) {
WC()->cart->add_to_cart( $product_id );
}
if ( $decoded->Uid ) {
WC()->session->set( 'uid', $decoded->Uid );
}
die();
};
and it now works properly.
Related
I have developed a payment gateway for WooCommerce. The thing is, when I developed it, the version of WooCommerce was 4.7.0 (It still is in my localhost) but in the production server the version is 5.1.0. I had to use a webhook like so:
function webhook() {
$data = json_decode($this->df_check_payment(), true);
$code = $data['result']['code'];
$description = $data['result']['description'];
if ($code != WC_Gateway_Datafast::DF_SUCCESS_CODE){
wc_add_notice( __("Payment failed -> Code: $code Description: $description" , 'gateway'), 'error' );
wp_safe_redirect( wc_get_page_permalink( 'cart' ) );
} else{
$orderId = $data['customParameters']['SHOPPER_documentoId'];
$order = wc_get_order( $orderId );
$order->set_transaction_id($data['id']);
$order->payment_complete();
wp_safe_redirect($this->get_return_url($order));
}
}
This works fine in localhost and the wc_add_notice is shown in the cart page but it's not working in production. I've tried with wc_get_page_permalink( 'checkout' ) but it doesn't work either, the notice is not shown. My guess is it has to do with the WC version but if that's the case, what's wrong? Did the API change? I really couldn't say if it was working in production with version 4.7.0 because I developed it before someone decided to update the production's wc plugin.
EDIT: I have updated the WC version in localhost and it works fine. Production still doesn't work. I thought maybe a plugin was putting something on top of the notice so it wasn't visible. I examined the HTML looking for the text in the notice but it's not there, which means it's not being generated at all.
This is how it looks in localhost (notice shows just fine):
And this is production (no notice whatsoever):
i've created a woocommerce plugin,
the plugin itself runs perfectly.
However as long as it takes for it to run, i'm experiencing wierd performances issues.
The website is totally inaccessible(both frontend and backend) ONLY from the browser that is logged in and ran the plugin.
Both frontend and backend are loading until the plugin finishes.
to make things even wierder it's working perfectly from another browser.
also this is run on a high-end dedicated server and when it's running the loads on the server are very low.
any clues?
require __DIR__ . '/vendor/autoload.php';
error_reporting(E_ALL);
ini_set('display_errors', 1);
include_once($_SERVER['DOCUMENT_ROOT'].'/wp-config.php');
use Automattic\WooCommerce\Client;
$woocommerce = new Client(woocommerce_api_url, api_key, api_secret,['version' => 'wc/v3','timeout' => '99999',]);
echo '<pre>';
$db = new DBfdr();
$i=0;
$page = 1;
$products = [];
$all_products = [];
do{
try {
$products = $woocommerce->get('products',array('per_page' => 100, 'page' => $page));
} catch(HttpClientException $e) {
die("Can't get products: $e");
}
$all_products = array_merge($all_products,$products);
$page++;
Notes: the DBfdr class contains a simple function for managing pdo connections to the sql server.
That piece of code doesn't look so good, why would you need to make a plugin that externally loads wp then going through Woocommerce Client Api to get the list of products and then cycle all of them to make an if condition.
That would be so much more efficient if you would just pass inside WP standard plugin structure, using global $wpdb class and performing your queries with some join.
That said, the problem you are facing could be solved by adding this before your code:
ignore_user_abort( true );
/* Don't make the request block till we finish, if possible. */
if ( function_exists( 'fastcgi_finish_request' ) && version_compare( phpversion(), '7.0.16', '>=' ) ) {
fastcgi_finish_request();
}
The problems occurs because the wp-config.php is included in the beggining.
wp-config.php in the end has
require_once(ABSPATH . 'wp-settings.php');
which inits some core wordpress functions which in turn "locks" the session.
i managed to fix the issue by removing
include_once($_SERVER['DOCUMENT_ROOT'].'/wp-config.php');
and replacing it with customs defines
I’m using Easy Digital Downloads for my Wordpress webshop. After someone buys a item it needs to add credits to the MySQL database. I got this working by adding PHP code to shortcode-receipt.php.
This is working correct but when I reload the receipt via browser or mail the PHP code will fire again:
php
<?php
if( edd_is_payment_complete( $payment->ID ) && edd_receipt_show_download_files( $item['id'], $edd_receipt_args, $item ) ) :
?>
Could someone help me out here?
What is the best method to fire PHP code when a payment is successful?
Thanks in advance!
There is action edd_complete_purchase which fires when order is completed.
So, in your case, I would remove the code from the shortcode and created an plugin. Inside the plugin should be something like this
function my_edd_receipt( $payment_id ){
if( edd_is_payment_complete( $payment_id ) && edd_receipt_show_download_files( $item['id'], $edd_receipt_args, $item ) ) :
}
add_action( 'edd_complete_purchase', 'my_edd_receipt');
before WooCommerce 3.0 came out my code had worked like a charm to save custom values from the cart into the order on checkout. But since then I'm not able to create custom meta for orders.
Environment: Wordpress 4.9.4 & WooCommerce 3.3.3
Hooks
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
add_action('woocommerce_checkout_create_order', 'custom_meta_to_order', 20, 1);
The Hook number 1 is the one I tried the most, the 2 one was just an experiment with some literal changes mentioned in this topic.
Function
The following functions-code is related to hook number 1:
if (!function_exists('custom_meta_to_order')) {
function custom_meta_to_order($order_id, $values) {
$order = wc_get_order( $order_id );
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($values['myValue'])) {
$myValue = $values['myValue'];
if (!empty($myValue)) $order->update_meta_data('_myKey', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
$order->save();
}
}
I've checked also in the mySQL table table wp_woocommerce_order_itemmeta if at least the two _TESTKEY*-meta-entrys will be created (because they don't have a condition).
But it seems that the meta-keys and values don't getting created via this hook and function.
The function itself getting called, so at least the hooks itselfs are working.
So my question is: "What am I doing wrong?"
UPDATED: There is some errors in your code…
Both hooks have only 1 argument (not 2, so $values doesn't exist)
To get your custom field you should use $_POST['myValue'] instead.
and other things like each hook has a different argument:
$order_id for woocommerce_checkout_update_order_meta
$order for woocommerce_checkout_create_order
Below I have replaced $_POST['myValue'] by $_POST['billing_country'] as you don't give the code for this custom checkout field…
So here are both ways:
1) The best way for me, as explained here:
if ( ! function_exists('custom_meta_to_order') ) {
add_action( 'woocommerce_checkout_create_order', 'custom_meta_to_order', 20, 1 );
function custom_meta_to_order( $order ) {
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($_POST['billing_country'])) {
$myValue = $_POST['billing_country'];
if (!empty($myValue)) $order->update_meta_data('_my_key', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
2) The other way:
if ( ! function_exists('custom_meta_to_order') ) {
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
function custom_meta_to_order( $order_id ) {
// get an instance of the WC_Order object
$order = wc_get_order( $order_id );
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($_POST['billing_country'])) {
$myValue = $_POST['billing_country'];
if (!empty($myValue)) $order->update_meta_data('_my_key', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
// Save the order data and meta data
$order->save();
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
The proof:
And (in database wp_postmeta table for this order ID):
Tested in WooCommerce version 3.3+
You can use the old way too (which works):
if ( ! function_exists('custom_meta_to_order') ) {
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
function custom_meta_to_order( $order_id ) {
update_post_meta( $order_id, '_TESTKEYstart', 'Hello' );
if ( isset( $_POST['billing_country'] ) ) {
$myValue = $_POST['billing_country'];
if (!empty($myValue))
update_post_meta( $order_id, '_my_key', $myValue);
}
update_post_meta( $order_id, '_TESTKEYend', 'Bye');
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
Related: Add extra meta for orders in Woocommerce
Because comments are really hard to read (because of to much restricted formatation), this answer is just a response to the answer from LoicTheAztec.
I wrote a longer answer but it seems gone, so I sorry now for the much shorter one!
First our misunderstanding
You understood that I would like to use custom values from products but in my case it was a little bit other. I wrote an external application which included the wp-load.php and posted then data back to the product-page into the cart.
So the problem showed up here was the attempt to write the data from the cart into the order on checkout.
Recommend ways doesn't worked at first
The recommend ways you suggested all doesn't worked. I also stripped them so much down that they have should work and just write something into the meta. I've no clue which plugin/theme-function pranked me this time here.
But I was able to solve the problem
And many more! Just because I found the blog-post where I found out in the past, how to do this and as addition to my personal luck the author wrote already the changes for WP3.0, related to this process.
Still your post helped me
The errors you showed me bugged me since then and because it was hard to follow and inspect everything with Sublime and CodeIntel (and my start with Symfony itself) I decided to buy PHPStorm which showed and allowed me to fix all of my deprecated (legacy-using) functions by updating them properly.
( Finally no more global-variables: Yay. )
I mean, showing up parameters inline and deprecation-strokes already did a great job. But a bug-free working code-intel/reference which doesn't dies on big projects is just awesome.
That's why I marked your answer now as solution, thanks. Otherwise I would have just fixed the problem maybe (thanks to the authors blog-post) but still would sit on a ticking time bomb.
I am a WP noob but very comfortable in PHP.
I am working with a client and we have built a product customization tool as an Angular.js single page application. When the product is finished being customized we are seeking to inject it into a WooCommerce cart so the client can check out. To do this we are $_POSTing the data to a PHP file in the root directory of the WP install. The code to catch it looks like:
require_once('./wp-load.php' );
global $woocommerce;
$woocommerce->session->set_customer_session_cookie(true);
$woocommerce->cart->empty_cart();
$id_arr = $_GET['productID'];
$pdfName = $_GET['pdfName'];
for($i=0; $i<count($id_arr); $i++){
$id = $id_arr[$i];
if ($id==0) continue;
if ($i==0){
$ret = $woocommerce->cart->add_to_cart($id, 1, '', '', array('pdfName'=>$pdfName));
}else{
$ret = $woocommerce->cart->add_to_cart($id);
}
}
wp_redirect(site_url().'/cart/');
The products are all correctly added to the cart but after checkout there is no sign of the metadata. After extensive research, I have found an article here: https://wpml.org/forums/topic/woocommerce-add-to-cart-does-not-work-with-wpml-activated/ that shows me that plugins can cause this behavior. So I have two specific questions?
Does my code make sense, am I creating the metadata array correctly?
Do I need to create something in WooCommerce called pdfName before I can do this?
Is there another way that metadata can be added to an order in
WooCommerce that may work around this problem?
It looks like you are adding the metadata correctly. However, as soon as you refresh, WooCommerce re-creates the cart data. Therefore you have to tell WooCommerce to maintain the metadata when it is pulling the cart from the stored session. Well, at least that is my understanding of it. So I think you need to filter thee $cart_item as it is run through the woocommerce_get_cart_item_from_session filter:
add_filter( 'woocommerce_get_cart_item_from_session', 'so_29660316_get_cart_item_from_session', 11, 2 );
function so_29660316_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['pdfName'] ) ) {
$cart_item['pdfName'] = $values['pdfName'];
}
return $cart_item;
}