I'm using Wordpress forms (gravity forms plugin) and I'm trying to pass price value to payment platform. I'm using just a hook with code that after form submission passes value to URL and redirects to payment page:
add_action('gform_after_submission', 'link_to_payment', 10, 2);
function link_to_payment($entry, $form) {
$price = $entry['6.2'];
header("Location: http://www.******.***/test.php?price='.$price");
exit();
}
Obviously problem with this is just that any person with webtools can change the value of $entry['6.2'] in html code and get a different price to pay. My question is, is there a safe way to pass value from HTML page to PHP code that user couldn't change in HTML code?
As these are the price of products which is set from the backend, you don't need to get the price from the frontend.
Create a new hidden field which has ID of the product. Let's say the name of field is 6.3.
add_action('gform_after_submission', 'bks_link_to_payment', 10, 2);
function bks_link_to_payment($entry, $form) {
$product_id = $entry['6.3']; // Make sure you change the field to the one you create.
$product = wc_get_product( $product_id ); // get product object from the backend.
// If the product exists.
if ( $product ) {
$price = $product->get_price(); // This would give you the price of the product.
header("Location: http://www.******.***/test.php?price='.$price");
exit();
}
}
So, in case someone changes the id of the product using webtools you are making sure that the product exists and the price is fetched from the database so it can't be altered.
Related
I have a custom input field in the WooCommerce cart for every cart item. When somebody clicks update cart I want to send the extra data to the server and process that data and add it to the current cart.
I can't find anywhere how to do this. Is this even possible?
I tried:
woocommerce_update_cart_action_cart_updated
in the $_POST variable the custom data is not available
Trough custom javascript
Run a ajax request every time the input field get's changed. But this is interfering with the regular way to update the WooCommerce cart. Lot's of bugs...
A hook before updating the cart
I can't find if there's a hook for sending extra data before updating the cart.
In the end the solution was quite simple. Since the cart is a regular HTML form you can add custom input data. When the cart is updated all the form data is serialised and sent trough with ajax. You just need to set the right name attribute on the input field.
It took the following steps:
Copy the woocommerce cart template.
Add your custom input in the cart item foreach loop
Give it the right name. Like this:
name="cart[<?php echo $cart_item_key; ?>][your_custom_key]"
Use the hook:
woocommerce_update_cart_action_cart_updated
In this hook you can easily access the $_POST['cart'] variable and do your stuff. For example:
$cart = WC()->cart->cart_contents;
// loop over the cart
foreach($_POST['cart'] as $cartItemKey => $values) {
$cartItem = $cart[$cartItemKey];
$yourCustomValue = $values['your_custom_key'];
// process the value, do something with it...
$cartItem['your_custom_key'] = $yourCustomValue;
WC()->cart->cart_contents[$cartItemKey] = $cartItem;
}
Et voilà. Now when you fill in the input field and update the cart, the data is stored in the cart. Now for example you can save the extra cart data on storing a new order or use the data to calculate a fee.
You can use it like this
add_filter( 'woocommerce_update_cart_action_cart_updated', function( $cart_updated ) {
$contents = WC()->cart->cart_contents;
foreach ( $contents as $key => &$item ) {
$contents[$key]['location'] = $_POST['cart'][$key]['location'];
$contents[$key]['pickup_on'] = $_POST['cart'][$key]['pickup_on'];
$contents[$key]['pickup_time'] = $_POST['cart'][$key]['pickup_time'];
$contents[$key]['pickup_day'] = $_POST['cart'][$key]['pickup_day'];
$contents[$key]['pickup_date'] = $_POST['cart'][$key]['pickup_date'];
$contents[$key]['testing'] = 'testing done!';
}
WC()->cart->set_cart_contents( $contents );
return true;
} );
I want to get the value of _product_id on the payout page (thankyou.php), can somebody help me with this.
I have attached an image of the field I need exactly that value
You can use woocommerce_thankyou hook to get the product ID's in
thankyou page
function wh_getProductIds($order_id)
{
//getting order object
$order = wc_get_order($order_id);
$product_id_arr = [];
//getting all line items
foreach ($order->get_items() as $item)
{
$product = $item->get_product();
$product_id_arr = $product->get_id(); //storing the product ID
//$product_sku = $product->get_sku();
}
//$product_id_arr has all the order's product IDs
//now you can do your stuff here.
}
add_action('woocommerce_thankyou', 'wh_getProductIds', 10, 1);
Code goes in functions.php file of your active child theme (or theme). Or also in any plugin php files.
Code is tested and works. version 3.x or above
Related:
Woocommerce Get Orders on Thank you page and pass data javascript snippet
WooCommerce Conversion Tracking Script for two Pixel
woocommerce_thankyou hook not working
Hope this helps!
I'm writing a custom WordPress function that will change the flat_rate shipping when a customer changes the "State" field from a select menu. Currently I'm doing it in my theme's functions.php
I have created a custom field to represent "State" field as a drop down menu in the billing fields. I used "WooCommerce Checkout Manager" plugin to setup the custom field and disabled the default "State" field.
Now I want to change the shipping cost depending on the value of my custom "State" field. I'm unable to retrieve the data of the field. Also I want to know what hook I can use to change the flat rate shipping once this field's value is changed.
I've used this filter hook (woocommerce_package_rates) and it doesn't work.
Here is my code to do it which I got it from another tutorial then made my customization
function wc_ninja_change_flat_rates_cost( $rates, $package ) {
$destination = $package['destination'];
$city = $destination['myfield12']; // getting the city field value
// Make sure flat rate is available
if ( isset( $rates['flat_rate'] ) ) {
if ( $city == 'Alex' || $city == 'الإسكندرية' ) {
// Set flat rate to cost $10 more
$rates['flat_rate']->cost = 30;
}
else {
$rates['flat_rate']->cost = 20;
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'wc_ninja_change_flat_rates_cost', 10, 2 );
I found this:
How to update shipping cost in cart dynamically (ajax) based on a custom field in WooCommerce
Basically it captures the field data through JS and send an Ajax request to the server which then stores the value in the session. Then adds an additional fee. It is not exactly what I was seeking to do but its a functional workaround.
Problem I am having here is that people go to a Product page, set a quantity on how much they want of that product and add to cart (which than takes them to the cart page). Client wants the ability to go back to the shop/product page if they want to make further changes to that product (honestly this is strange, since they can do this on the cart page, but whatever). But when people go to update the quantity on the product page, instead of updating the quantity, it adds to the existing quantity for that product.
How to get it to update the existing quantity when the quantity has been submitted more than once on the product page? Is there a woocommerce loop that I can take advantage of here?
Thanks guys, I have dug through the plugin and coded the solution below:
add_action('woocommerce_add_to_cart_handler', 'update_product_in_cart', 11, 2);
function update_product_in_cart($p, $q) {
global $woocommerce;
$cartItem = $woocommerce->cart->cart_contents;
$currentProductId = $q->id;
$wCart = $woocommerce->cart->get_cart();
// If cart already exists, and product exists, than remove product, and add the new product to it.
if ($wCart)
{
$cart_item_keys = array_keys($wCart);
foreach($cart_item_keys as $key)
{
foreach($cartItem as $item)
{
$productItemId = $item['product_id'];
if ($productItemId == $currentProductId)
{
// If you want to empty the entire cart...
// $woocommerce->cart->empty_cart();
// If you want to remove just the product from the cart...
$woocommerce->cart->set_quantity($key, 0);
}
}
}
}
// This adds the product to the cart...
return $q;
}
This gets added to functions.php, and basically, if the product id exists in the cart, it removes the product and the return of $q adds in the new product info.
Works a charm!
I did not want to post here but I could not find the answer I was looking for and I do not have enough reputation to comment on other VERY SIMILAR questions to get my exact answer.
I found an almost perfect answer from this post: WooCommerce: Add product to cart with price override?
using the code:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price');
function add_custom_price( $cart_object ) {
$custom_price = 10; // This will be your custome price
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = $custom_price;
}
}
and it works great...if you set a hard coded custom price.
My question is: How can I set a custom price based on user input?
I have tried every way I can think of to pass information (I even tried using cookies, globals, sessions) and none of them worked how I wanted and all of them were, at BEST, hacks.
The specific product in question is a donation and the customer wants the user to be able to set the donation price (rather than just creating a variable product with set price points).
On the donation page when the user submits the donation form I am adding the donation product to the cart like so:
$donation_success = $woocommerce->cart->add_to_cart($donation_id);
My donation product has a set price of 0.00 so when it is added to the cart it has a price of 0.00 (I don't know if the price is set at this point or later)
I have tried passing in information at this point using the last variable in the add_to_cart method which accepts an array of arguments but I couldn't seem to get that to work either.
I am sure the answer is simple but I have been trying for hours to do this right and I cannot get it to work. I am out of ideas.
The actual code I am using at the moment is slightly different than was suggested by the answerer of the above post but works basically the same:
add_action( 'woocommerce_before_calculate_totals', 'woo_add_donation');
function woo_add_donation() {
global $woocommerce;
$donation = 10;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if($cart_item['data']->id == 358 || $cart_item['data']->id == 360){
$cart_item['data']->set_price($donation);
}
}
}
Thanks in advance for any helpful advice!
I found a solution which is not elegant but works for my purposes.
I was trying to use cookies before but I didn't set the cookie path so it was only available to the page it was set on.
I am now setting a cookie with the donation price:
setcookie("donation", $_GET['donation'], 0, "/");
Then I am setting the price like so:
add_action( 'woocommerce_before_calculate_totals', 'woo_add_donation');
function woo_add_donation() {
global $woocommerce;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if($cart_item['data']->id == 358 && ! empty($_COOKIE['donation'])){
$cart_item['data']->set_price($_COOKIE['donation']);
}
}
}
I have been looking for exactly the same thing. I found this WooCommerce plugin (not free) for this
name your price plugin
Initially I wasn't sure what search terms to use to find plugins like this but it looks like "WooCommerce name your price" brings up links to other sources of similar plugins.
[this is a comment] Where do you set the cookie? My first guess is that the refreshes in the same page, using the GET method, and provides a PHP code-block with the $_GET['donation'] to set the cookie with.
And then, once the cookie is set, you redirect the page to Woocommerce Cart page to continue the shopping process. If you're doing it easier way, please let me know. Thanks.
Sorry, I couldn't post this as a comment to the selected answer due to the lack of points.
This code will create order with custom price:
$product = wc_get_product($product_id);
$order = wc_create_order();
try {
$order->add_product($product);
//$order->set_customer_id($user->ID);
$order->set_billing_email($customer_email);
} catch (WC_Data_Exception $e) {
wp_send_json_error("Failed to create order");
}
$order->calculate_totals();
try {
$order->set_total($custom_price); // $custom_price should be float value
} catch (WC_Data_Exception $e) {
wp_send_json_error("Failed to change order details");
}
$order->save();
$order->update_status( 'completed' );