I'm trying to disable a couple of payment gateways based on a user's role. The function & hook I found works on the Paypal method but not Amazon Payments Advanced. Here's my code:
function wk_disable_gateways( $available_gateways ) {
global $woocommerce;
$wholesale_cust = check_user_role( array( 'wholesale', 'orig-wholesale' ) );
if ( isset( $available_gateways['paypal'] ) && $wholesale_cust ) {
unset( $available_gateways['paypal'] );
}
if ( isset( $available_gateways['amazon_payments_advanced'] ) && $wholesale_cust ) {
unset( $available_gateways['amazon_payments_advanced'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'wk_disable_gateways' );
The "Pay with Amazon" code is still running on the checkout page. Any ideas?
This is not the best solution, but I have not been able to find a more viable answer.
First off I did what you did and disabled all gateways expect the one I wanted the user to use. In my case I only want someone to check out with the nmigateway.
This goes inside of your theme functions.php
add_filter( 'woocommerce_available_payment_gateways', 'filter_gateways', 1);
function filter_gateways( $gateways ){
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
foreach ( $gateways as $gateway_key => $gateway ) {
if ( $gateway_key !== 'nmipay' ) {
unset( $gateways[ $gateway_key ] );
}
}
}
}
return $gateways;
}
Next here is the part that makes this not the best solution editing the plugins source code.
Change the following two functions inside of the plugins/woocommerce-gateway-amazon-payments-advanced/amazon-payments-advanced.php
/**
* Checkout Button
*
* Triggered from the 'woocommerce_proceed_to_checkout' action.
*/
function checkout_button() {
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
$disable_button = true;
}
}
if(!isset($disable_button) && $disable_button !== true ){
?><div id="pay_with_amazon"></div><?php
}
}
/**
* Checkout Message
*/
function checkout_message() {
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
$disable_button = true;
}
}
if(!isset($disable_button) && $disable_button !== true ){
if ( empty( $this->reference_id ) ) {
echo '<div class="woocommerce-info info"><div id="pay_with_amazon"></div> ' . apply_filters( 'woocommerce_amazon_pa_checkout_message', __( 'Have an Amazon account?', 'woocommerce-gateway-amazon-payments-advanced' ) ) . '</div>';
}
}
}
Keep in mind that when the plugin is updated all of your changes will be lost.
Related
After the newer release of WooCommerce 3.X , the code written for WoCommerce 2.X doesn't work anymore without throwing error on the product type line.
function remove_bundled_items_from_cart( $cart_item_key, $instance ) {
if ( ! empty( $instance->removed_cart_contents[$cart_item_key] ) ) {
$product_id = $instance->removed_cart_contents[$cart_item_key]['product_id'];
$product_type = $instance->removed_cart_contents[$cart_item_key]['data']->product_type;
if ( $product_type == 'bundle' ) {
if (is_array($instance->cart_contents) || is_object($instance->cart_contents)) {
foreach ( $instance->cart_contents as $key => $cart_item ) {
if ( isset( $cart_item['is_bundled_item'] ) && $cart_item['is_bundled_item'] == $product_id ) {
WC()->cart->remove_cart_item( $key );
}
}
}
}
}
}
add_action( 'woocommerce_cart_item_removed', 'remove_bundled_items_from_cart', 10, 2 );
Does anybody know what I need to change to be able to have the $product_type stop throwing a error?
I would still need to be able to check if the string is "bundle", so I need somehow to get the information fetched.
As the main error in your code comes from:
$product_type = $instance->removed_cart_contents[$cart_item_key]['data']->product_type;
The $instance->removed_cart_contents[$cart_item_key]['data'] is the WC_Product Object instance and since WC versions 3+ WC_Product properties can't be accessed directly anymore.
Instead you will use the WC_Product method get_type() (or the conditional method is_type())…
As $instance->removed_cart_contents[$cart_item_key]['data'] doesn't exist in simple products, you need to test it in your first condition.
This should avoid throwing errors (on the product type line…):
add_action( 'woocommerce_cart_item_removed', 'remove_bundled_items_from_cart', 10, 2 );
function remove_bundled_items_from_cart( $cart_item_key, $instance ) {
if ( ! empty( $instance->removed_cart_contents[$cart_item_key]['data'] ) ) {
$product_id = $instance->removed_cart_contents[$cart_item_key]['product_id'];
$product = $instance->removed_cart_contents[$cart_item_key]['data']; // The WC_Product object
if ( $product->is_type( 'bundle' ) ) {
if (is_array($instance->cart_contents) || is_object($instance->cart_contents)) {
foreach ( $instance->cart_contents as $key => $cart_item ) {
if ( isset( $cart_item['is_bundled_item'] ) && $cart_item['is_bundled_item'] == $product_id ) {
WC()->cart->remove_cart_item( $key );
}
}
}
}
}
}
BUT I don't see in the raw cart data output any 'is_bundled_item' key…
Instead you can use in your code one of this available cart array keys:
bundled_by key (the parent WC_Bundle_Product cart item key)
bundled_item_id key (the child bundle item ID)
So you could replace in your code 'is_bundled_item' like:
add_action( 'woocommerce_cart_item_removed', 'remove_bundled_items_from_cart', 10, 2 );
function remove_bundled_items_from_cart( $cart_item_key, $instance ) {
if ( ! empty( $instance->removed_cart_contents[$cart_item_key]['data'] ) ) {
$product = $instance->removed_cart_contents[$cart_item_key]['data'];
if ( $product->is_type( 'bundle' ) ) {
if (is_array($instance->cart_contents) || is_object($instance->cart_contents)) {
foreach ( $instance->cart_contents as $key => $cart_item ) {
if ( isset( $cart_item['bundled_item_id'] ) && $cart_item['bundled_by'] == $cart_item_key ) {
WC()->cart->remove_cart_item( $key );
}
}
}
}
}
}
This should work totally…
I'm creating a WooCommerce add-on to customize the product, based on selected options by the visitor and custom price is calculated and stored into session table also.
I am able to get that value in cart page also.
My problem: I would like to change the default price of the product and replace it with new calculated value in the WooCommerce process as cart, checkout, payment, mail notifications, order...
Any advice please?
Thanks
Ce right hook to get it working is woocommerce_before_calculate_totals. But you will have to complete (replace) the code to get the new price in the hooked function below:
add_action( 'woocommerce_before_calculate_totals', 'custom_cart_items_prices', 10, 1 );
function custom_cart_items_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop Through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get the product id (or the variation id)
$product_id = $cart_item['data']->get_id();
// GET THE NEW PRICE (code to be replace by yours)
$new_price = 500; // <== Add your code HERE
// Updated cart item price
$cart_item['data']->set_price( $new_price );
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works on WooCommerce versions 3+. But as you don't give any code I can't test it for real getting the new price from session…
function save_subscription_wrap_data( $cart_item_data, $product_id ) {
$include_as_a_addon_subscription = get_field('include_as_a_addon_subscription',$product_id);
$subscricption_product_data = get_field('subscricption_product',$product_id);
$current_user = is_user_logged_in() ? wp_get_current_user() : null;
$subscriptions = wcs_get_users_subscriptions( $current_user->ID );
if($include_as_a_addon_subscription == "yes")
{
foreach ( $subscriptions as $subscription_id => $subscription ) {
$subscription_status = $subscription->get_status();
}
if($subscription_status == 'active')
{
$cart_item_data[ "subscribe_product" ] = "YES";
}
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_subscription_wrap_data', 99, 2 );
function render_meta_on_cart_and_checkout1( $cart_data, $cart_item = null ) {
$meta_items = array();
if( !empty( $cart_data ) ) {
$meta_items = $cart_data;
}
if( isset( $cart_item["subscribe_product"] ) ) {
$meta_items[] = array( "name" => "Product Type", "value" => "Package Addon" );
}
return $meta_items;
}
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout1', 100, 2 );
function calculate_gift_wrap_fee( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" )) {
$additionalPrice = 100;
foreach ( WC()->cart->get_cart() as $key => $value ) {
if( isset( $value["subscribe_product"] ) ) {
if( method_exists( $value['data'], "set_price" ) ) {
$orgPrice = floatval( $value['data']->get_price() );
//$value['data']->set_price( $orgPrice + $additionalPrice );
$value['data']->set_price(0);
} else {
$orgPrice = floatval( $value['data']->price );
//$value['data']->price = ( $orgPrice + $additionalPrice );
$value['data']->price = (0);
}
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 99 );
I have function in functions.php , which automatically adds woocommerce product by ID to cart when website is visited.
The website is bilingual and the function can't determine translated product ID.
So, I want to know if is possible to add wpml function in functions.php, which determines first language of front end, then executes function, something like this:
<?php if(wpml_getLanguage()=='en'); ?>
---do function for product 22---
<?php elseif(wpml_getLanguage()=='it'); ?>
---do function for product 45--
<?php endif; ?>
My code:
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 22;
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
You can easily get this by using the native WPML variable ICL_LANGUAGE_CODE.
You can find more information about this topic on the following page:
https://wpml.org/documentation/support/wpml-coding-api/
This can be dropped into functions.php
add_action( 'init', 'add_product_on_language' );
function add_product_on_language(){
if ( ! is_admin() ) {
if( ICL_LANGUAGE_CODE == 'en' ){
$product_id = 22;
} elseif ( ICL_LANGUAGE_CODE == 'it' ) {
$product_id = 45;
}
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
I'm using the code below to modify the WooCommerce Is_Purchasable option so that, item Y is purchasable if item X is added to the cart.
But it gives ajax error when trying to add item Y to the cart.
Here's the code:
function aelia_get_cart_contents() {
$cart_contents = array();
/**
* Load the cart object. This defaults to the persistant cart if null.
*/
$cart = WC()->session->get( 'cart', null );
if ( is_null( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart', true ) ) ) {
$cart = $saved_cart['cart'];
} elseif ( is_null( $cart ) ) {
$cart = array();
}
if ( is_array( $cart ) ) {
foreach ( $cart as $key => $values ) {
$_product = wc_get_product( $values['variation_id'] ? $values['variation_id'] : $values['product_id'] );
if ( ! empty( $_product ) && $_product->exists() && $values['quantity'] > 0 ) {
if ( $_product->is_purchasable() ) {
// Put session data into array. Run through filter so other plugins can load their own session data
$session_data = array_merge( $values, array( 'data' => $_product ) );
$cart_contents[ $key ] = apply_filters( 'woocommerce_get_cart_item_from_session', $session_data, $values, $key );
}
}
}
}
return $cart_contents;
}
// Step 1 - Keep track of cart contents
add_action('wp_loaded', function() {
// If there is no session, then we don't have a cart and we should not take
// any action
if(!is_object(WC()->session)) {
return;
}
// Product Y
global $y_cart_items;
$y_cart_items = 2986;
//Product X
global $x_cart_items;
$x_cart_items = array(
'297'
);
// Step 2
add_filter('woocommerce_is_purchasable', function($is_purchasable, $product) {
global $y_cart_items;
global $x_cart_items;
if( $product->id == $y_cart_items ) {
// make it false
$is_purchasable = false;
// get the cart items object
foreach ( aelia_get_cart_contents() as $key => $item ) {
// do your condition
if( in_array( $item['product_id'], $x_cart_items ) ) {
// Eligible product found on the cart
$is_purchasable = true;
break;
}
}
}
return $is_purchasable;
}, 10, 2);
}, 10);
// Step 3 - Explain customers why they can't add some products to the cart
add_filter('woocommerce_get_price_html', function($price_html, $product) {
if(!$product->is_purchasable() && is_product()) {
$price_html .= '<p>' . __('Add Product X to be able to purchase Product Y.', 'woocommerce') . '</p>';
}
return $price_html;
}, 10, 2);
How do I fix this? Thank you.
I have searched far and wide for a solution to add a free item (that I have hidden with woocommerce) to the cart when someone enters the hiddenproduct coupon I made. This is the code that I am using, it is a modified version of this:http://docs.woothemes.com/document/automatically-add-product-to-cart-on-visit/. The difference is instead of using the cart total to add it, I am trying to use the applied coupon.
Here is my current code and it is not adding the product to the cart:
add_action( 'init', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 1211;
$found = false;
$coupon_id = 1212;
if( $woocommerce->cart->applied_coupons == $coupon_id ) {
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
$woocommerce->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
$woocommerce->cart->add_to_cart( $product_id );
}
}
}
}
I am pretty sure that the error is happening here '( $woocommerce->cart->applied_coupons == $coupon_id )' but I do not know the correct identifiers.
This is in my functions.php
Can anyone help me out? Thank you
I was in a similar situation and used some of your code and made some tweaks.. This worked for me: if(in_array($coupon_id, $woocommerce->cart->applied_coupons)){
Cheers!
I know this is ancient, but I had basically the same need. So I thought I'd go ahead and post my solution. I'm hardly an expert on any of this, so I'm sure there's plenty of room for improvement. I put this in my functions.php (obviously borrowing a lot from the original post here):
function mysite_add_to_cart_shortcode($params) {
// default parameters
extract(shortcode_atts(array(
'prod_id' => '',
'sku' => '',
), $params));
if( $sku && !$prod_id ) $prod_id = wc_get_product_id_by_sku($sku);
if($prod_id) {
$cart_contents = WC()->cart->get_cart_contents();
if ( sizeof( $cart_contents ) > 0 ) {
foreach ( $cart_contents as $values ) {
$cart_prod = $values['product_id'];
if ( $cart_prod == $prod_id ) $found = true;
}
// if product not found, add it
if ( ! $found ) WC()->cart->add_to_cart( $prod_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $prod_id );
}
}
return '';
}
add_shortcode('mysite_add_to_cart','mysite_add_to_cart_shortcode');
add_action( 'woocommerce_applied_coupon', 'mysite_add_product' );
function mysite_add_product($coupon_code) {
$current_coupon = new WC_Coupon( $coupon_code );
$coupon_description = $current_coupon->get_description();
do_shortcode($coupon_description);
return $coupon_code;
}
This lets me add a shortcode in the coupon description that specifies what product should get added when the coupon is applied. It can be either [mysite_add_to_cart prod_id=1234] or [mysite_add_to_cart sku=3456]. So far it seems to be working fine.