woocommerce apply coupon programmatically bug - php

This is the code I am using:
if (!is_admin()):
add_action( 'woocommerce_before_cart', 'apply_matched_coupons' );
//add_action('woocommerce_before_cart_table', 'apply_matched_coupons');
//add_action('woocommerce_before_checkout_form', 'apply_matched_coupons');
function apply_matched_coupons() {
global $woocommerce;
$coupon_code = 'somecodehere';
if ( $woocommerce->cart->has_discount( $coupon_code ) ) return;
if ( $woocommerce->cart->cart_contents_total >= 1 ) {
$woocommerce->cart->add_discount( $coupon_code );
wc_print_notices();
}
}
endif;
The issue I am having is that when I go to the checkout page that the coupon still gets applied. It's not applied on the cart which is the desired result but I don't want it applied at all in this condition.
Any help?

Based on your explanation, it sounds like you should be using the woocommerce_add_to_cart hook, which is run when a product is successfully added to the cart. I also don't think you should be using is_admin(), since that just checks if you're on an admin page...not if the current user is an admin.
I would do something like the following:
add_action( 'woocommerce_add_to_cart', 'apply_matched_coupons' );
function apply_matched_coupons() {
// If the current user is a shop admin
if ( current_user_can( 'manage_woocommerce' ) ) return;
// If the user is on the cart or checkout page
if ( is_cart() || is_checkout() ) return;
$coupon_code = 'somecodehere';
if ( WC()->cart->has_discount( $coupon_code ) ) return;
WC()->cart->add_discount( $coupon_code );
}

Related

Woocommerce - Hide payment gateway “cod - cash on delivery” and show bacs - Bank Transfer

Please Guys,
I use two payment gateways on the checkout page:
1° bacs = Bank transfer
2° cod = Cash on Delivery
i need to hide the payment gateway COD = Cash on Delivery, If the user has No Admin Profile (!is_user_admin()), || or it's not logged, || ! is_user_logged_in() then hide.
This is the code that i'm using and it's working.
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_cod_hide' );
function bbloomer_cod_hide( $available_gateways ) {
if ( isset( $available_gateways['cod']) && !is_user_admin() ) {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}
The problem is...the payment gateway bacs = Bank transfer is also affected and hidden : )
so i tried with this another hook
add_filter( 'woocommerce_available_payment_gateways', 'transfer_enable_bacs' );
function transfer_enable_bacs( $available_gateways ) {
if ( isset( $available_gateways['bacs']) && !is_user_admin() ) {
//unset( $available_gateways['bacs'] );
}
return $available_gateways;
}
But this is not the correct solution. Both payment gateways are hidden.
What am i doing wrong please?
Gratitude!
I think you need to replace is_user_admin with current_user_can
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_cod_hide' );
function bbloomer_cod_hide( $available_gateways ) {
if ( isset( $available_gateways['cod'] ) && ! current_user_can( 'administrator' ) ) {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}
is_user_admin does not check if the user is an administrator; use current_user_can() for checking roles and capabilities.
https://developer.wordpress.org/reference/functions/is_user_admin/
try the following code:
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_cod_hide' );
function bbloomer_cod_hide( $available_gateways ) {
if ( !is_user_logged_in() ) || !current_user_can( 'install_themes' ) ) {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}

Remove WooCommerce subscription interval from cart and checkout pages

I am trying to remove the / month or / year on the cart and checkout page for Woocommerce Subscriptions.
So Instead of $99 / year I only want to show $99
Hoping someone can point me i. the right direction.
Thank you
You can try using the following, that will clean everything except the recurring price and totals:
// Items pricing
add_filter( 'woocommerce_subscriptions_product_price_string', 'filter_wc_subscriptions_product_price_string', 10, 3 );
function filter_wc_subscriptions_product_price_string( $price_string, $product, $args ) {
if ( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
return $args['price'];
}
return $price_string;
}
// Total lines
add_filter( 'woocommerce_subscription_price_string', 'filter_wc_subscription_price_string', 10, 2 );
function filter_wc_subscription_price_string( $subscription_string, $subscription_details ) {
if ( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
$recurring_amount = $subscription_details['recurring_amount'];
if( is_numeric( $recurring_amount ) ) {
return strip_tags( wc_price($recurring_amount) ); // For shipping methods
}
else {
return $recurring_amount;
}
}
return $subscription_string;
}
Based on:
WooCommerce Subscriptions Filter Reference documentation
Hide the "free trial" text from Woocommerce Subscriptions price

Check WooCommerce User Role and Payment Gateway and if they match - Apply fee

I'm struggling with applying a fee for an array of user roles if and when a specific payment gateway is selected.
The code I've written works fine if I do not check the user role, but once I try and do that, it does not.
I've removed (commented) the user role if statement in the code and I'm asking for help making it work.
I need to check if the user role match my array and if it does, check the payment gateway. If the payment gateway match too, apply the fee.
This is my code:
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee', 20, 1 );
function custom_fee ($cart){
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) return;
if (!is_checkout() && !is_wc_endpoint_url()) return;
$customer_role = wp_get_current_user();
$roles_to_check = array( 'vendor', 'external' );
$payment_method = WC()->session->get('chosen_payment_method');
// if (!in_array($roles_to_check, $customer_role->roles)) return;
if ('bacs' == $payment_method){
$payment_fee = $cart->subtotal * 0.05;
$cart->add_fee( 'Payment Fee', $payment_fee, true );
}
}
You could use the following, explanation with comments added in the code
Conditions that must be met in this code are:
only for certain user roles
checks on payment method
function custom_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) )
return; // Only checkout page
if ( ! is_user_logged_in())
return;
// Get current WP_User Object
$user = wp_get_current_user();
// User roles
$roles = ( array ) $user->roles;
// Roles to check
$roles_to_check = array( 'vendor', 'external', 'administrator' );
// Compare
$compare = array_diff( $roles, $roles_to_check );
// Result is empty
if ( empty ( $compare ) ) {
// Payment method
$payment_method = WC()->session->get('chosen_payment_method');
// Condition equal to
if ( $payment_method == 'bacs' ) {
// Calculate
$payment_fee = $cart->subtotal * 0.05;
// Add fee
$cart->add_fee( 'Payment Fee', $payment_fee, true );
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee', 10, 1 );
EDIT
To complete my answer, see the answer from #LoicTheAztec
The answer of #7uc1f3r is good, but something important is missing from it.
In WooCommerce checkout when choosing a payment method, checkout totals are not refreshed. So something additional is required to refresh checkout "order review" section:
// jQuery - Update checkout on payment method change
add_action( 'wp_footer', 'custom_checkout_jquery_script' );
function custom_checkout_jquery_script() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
endif;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related: Add fee based on specific payment methods in WooCommerce

Set a custom calculated item price in Woocommerce mini-cart / Cart

Currently i have some custom calculation of product price based on different situation. When customer added a product in to cart then the custom price is set in session data , cart_item_data['my-price'] and i implemented using add_filter( 'woocommerce_add_cart_item') function and everything seems to working now .
Now the price in view cart page, checkout page is correct with my cart_item_data['my-price'].
But the only problem i am facing is the price is not updated in woocommerce mini cart that is appeared in the menu ,How can i change this ?
When i google i see a filter
add_filter('woocommerce_cart_item_price');
but i can't understand how to use this i do the following
add_filter('woocommerce_cart_item_price','modify_cart_product_price',10,3);
function modify_cart_product_price( $price, $cart_item, $cart_item_key){
if($cart_item['my-price']!==0){
$price =$cart_item['my-price'];
}
return $price;
//exit;
}
Here individual price is getting correct , but total price is wrong
Updated (october 2021)
For testing this successfully (and as I don't know how you make calculations), I have added a custom hidden field in product add to cart form with the following:
// The hidden product custom field
add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
function add_gift_wrap_field() {
global $product;
// The fake calculated price
?>
<input type="hidden" id="my-price" name="my-price" value="115">
<?php
}
When product is added to cart, this my-price custom field is also submitted (posted). To set this value in cart object I use the following function:
add_filter( 'woocommerce_add_cart_item', 'custom_cart_item_prices', 20, 2 );
function custom_cart_item_prices( $cart_item_data, $cart_item_key ) {
// Get and set your price calculation
if( isset( $_POST['my-price'] ) ){
$cart_item_data['my-price'] = $_POST['my-price'];
// Every add to cart action is set as a unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
Now to apply (set) the new calculated price my-price to the cart item, I use this last function:
// For mini cart *(cart item displayed price)*
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price, $cart_item ) {
if ( ! is_checkout() && isset($cart_item['my-price']) ) {
$args = array( 'price' => floatval( $cart_item['my-price'] ) );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price;
}
add_action( 'woocommerce_before_calculate_totals', 'set_calculated_cart_item_price', 20, 1 );
function set_calculated_cart_item_price( $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 ){
if( isset( $cart_item['my-price'] ) && ! empty( $cart_item['my-price'] ) || $cart_item['my-price'] != 0 ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( $cart_item['my-price'] );
}
}
}
All code goes in function.php file of your active child theme (or active theme).
Tested and works

Woocommerce Role Based Payment and minimum Subtotal

Currently I'm working on a WC-Project and I'm stucked. With this snippet it's showing the payment method "bacs" only when the subtotal is over 100. This works fine!
add_filter( 'woocommerce_available_payment_gateways', 'mmx_remove_bacs', 1 );
function mmx_remove_bacs( $gateways ){
global $woocommerce;
if ( $woocommerce->cart->subtotal < 100 ) {
unset($gateways['bacs']);
}
return $gateways;
}
Now this snippet above should only work when a customer is in the Checkout that has the userrole "customer". For this I have this seperate snippet:
Function enable_payment( $available_gateways ) {
global $woocommerce;
if ( isset( $available_gateways['bacs'] ) && !current_user_can('customer') ) {
unset( $available_gateways['bacs'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'enable_payment' );
My question now is, how can I bring this to snippets together, that it works as I wish?

Categories