WooCommerce: Change payment gateway if Cart Total amount = 0 - paypal

I want users to have a free checkout for my subscription service if they have 100% discount coupon code for the product. So if cart total gets equal to zero, then there should be no payment gateway and users should be able to signup directly.
I think WooCommerce don't allow working without payment gateway or can be difficult to modify, so I want to change the current payment gateway to "Cash on Delivery" if cart total equals to 0 . I shall change Cash on delivery text to something else later.
Here is link to my dummy development.
Use Couponcode: abcd1234
Here is the function that I'm using to hide payment gateways in my functions.php file :
add_filter( 'woocommerce_available_payment_gateways', 'paypal_100' );
function paypal_100($available_gateways) {
if ( WC()->cart->total == '0' ) {
unset( $available_gateways);
}
return $available_gateways;
}
Thanks in advance,
Yash

Well, after 6 hours of R & D here is the solution.
I made a minor change in plugins\woocommerce-subscriptions\classes\class-wc-subscriptions-cart.php And everything is working as I wanted. No payment method is required for subscription products if cart total equal to 0.
Before code (Line - 280 ):
public static function cart_needs_payment( $needs_payment, $cart ) {
if ( self::cart_contains_subscription() ) {
$is_for_one_period = ( self::get_cart_subscription_length() > 0 && self::get_cart_subscription_length() == self::get_cart_subscription_interval() ) ? true : false;
if ( $cart->total == 0 && false === $needs_payment && $cart->recurring_total > 0 && false === $is_for_one_period && 'yes' !== get_option( WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no' ) ) {
$needs_payment = true;
}
}
After Code:
public static function cart_needs_payment( $needs_payment, $cart ) {
if ( self::cart_contains_subscription() ) {
$is_for_one_period = ( self::get_cart_subscription_length() > 0 && self::get_cart_subscription_length() == self::get_cart_subscription_interval() ) ? true : false;
if ( $cart->total == 0 && false === $needs_payment && $cart->recurring_total > 0 && false === $is_for_one_period && 'yes' !== get_option( WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no' ) ) {
$needs_payment = false;
}
}
I just changed "$needs_payment = true;" to "$needs_payment = false;"

You can use the following code snippet.
So we check if the a specific pay method is available and check if the total amount in the shopping cart is equal to some amount. Then we can hide that payment method. In your case, you can hide all available methods.
function payment_gateway_disable_total_amount( $available_gateways ) {
global $woocommerce;
if ( isset( $available_gateways['paypal'] ) && $woocommerce->cart->total == 0 ) {
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_total_amount' );

Related

How to make phone number field a unique identifier like email in OSclass

I dont want users to register thesame phone number more than once just like email in OSclass registration page. I tried to duplicate and tweak the code for email like the one below but after clicking the submit button i got an error, thanks in advance i dont mind a github plugin for this
if( !osc_validate_email($input['s_email']) ) {
$flash_error .= _m('The email is not valid') . PHP_EOL;
$error[] = 5;
}
$email_taken = $this->manager->findByEmail($input['s_email']);
if( $email_taken != false ) {
osc_run_hook('register_email_taken', $input['s_email']);
$flash_error .= _m('The specified e-mail is already in use') . PHP_EOL;
$error[] = 3;
}
if($input['s_username']!='') {
$username_taken = $this->manager->findByUsername($input['s_username']);
if( !$error && $username_taken != false ) {
$flash_error .= _m( 'Username is already taken' ) . PHP_EOL;
$error[] = 8;

Redirect to different thank you pages on specific shipping method selection

I have two different shipping method on my WooCommerce site COD & local pickup, I want to redirect on two different thank you page depending on which shipping method the buyer choose. I tried this but its showing an error after purchase
add_action( 'template_redirect', 'woo_custom_redirect_after_purchase' );
function woo_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty( $wp->query_vars['order-received'] )) {
if( $order->has_shipping_method('flat_rate:21') ){
wp_redirect( 'mysite.com/thank-you-1/' );
exit;
}
elseif( $order->has_shipping_method('local_pickup:24') ) {
wp_redirect( 'mysite.com/thank-you-2/' );
exit;
}
}
}
You can use woocommerce_thankyou
add_action( 'woocommerce_thankyou', 'woo_custom_redirect_after_purchase');
function woo_custom_redirect_after_purchase( $order_id ){
$order = wc_get_order( $order_id );
if( $order->has_shipping_method('flat_rate:21') ){
wp_redirect( 'mysite.com/thank-you-1/' );
exit;
}elseif( $order->has_shipping_method('local_pickup:24') ) {
wp_redirect( 'mysite.com/thank-you-2/' );
exit;
}
}

Company field not required woocommerce [duplicate]

I'd like to make billing company and shipping company not required in WooCommerce. For some reason the code I am using works for EVERYTHING except for the company part. It turns out a third party plugin is making the company name required, here is the full code of that plugin:
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
require_once('legacy_pakkelabels_shipping_main.php');
/**
* #class Pakkelabels_Shipping_GLS_Business_Legacy
* #version 0.1.0
* #author Magnus Vejlø - Pakkelabels
*/
class Legacy_Pakkelabels_Shipping_GLS_Business extends Legacy_Pakkelabels_Shipping_Main
{
public function __construct($instance_id = 0)
{
$this->id = 'legacy_pakkelabels_shipping_gls_business';
$this->instance_id = absint($instance_id);
$this->method_title = __('GLS Business ', 'woocommerce-pakkelabels');
$this->method_description = __('Adds the option to ship with the GLS business to the checkout', 'woocommerce-pakkelabels');
$this->init();
}
/* add the diffrent actions */
function addActions()
{
//adds the shipping method to the WooCommerce
add_filter('woocommerce_shipping_methods', array($this, 'register_shipping_method'));
add_action('woocommerce_after_shipping_rate', array($this, 'pakkelabels_shipping_gls_business_show_below_shipping'));
add_action('woocommerce_checkout_process', array($this, 'pakkelabels_shipping_gls_business_field_process'));
}
function addFilters()
{
}
function pakkelabels_shipping_gls_business_field_process() {
global $woocommerce;
$choosen_shipping_method1 = preg_replace('/\d/', '', $woocommerce->session->chosen_shipping_methods[0] );
$choosen_shipping_method2 = preg_replace('/\d/', '', $woocommerce->session->chosen_shipping_methods );
if((isset($_POST['ship_to_different_address']) && ($_POST['shipping_company'] == '' || !isset($_POST['shipping_company']))) && ($choosen_shipping_method1 == "legacy_pakkelabels_shipping_gls_business" || $choosen_shipping_method2 == "legacy_pakkelabels_shipping_gls_business")){
if ( version_compare( $woocommerce->version, '2.1', '<' ) ) {
$woocommerce->add_error(__('Please fill out the Shipping company', 'woocommerce-pakkelabels'));
} else {
wc_add_notice( __('Please fill out the Shipping company', 'woocommerce-pakkelabels') , 'error');
}
}
if((!isset($_POST['ship_to_different_address']) && ($_POST['billing_company'] == '' || !isset($_POST['billing_company']))) && ($choosen_shipping_method1 == "legacy_pakkelabels_shipping_gls_business" || $choosen_shipping_method2 == "legacy_pakkelabels_shipping_gls_business")){
if ( version_compare( $woocommerce->version, '2.1', '<' ) ) {
$woocommerce->add_error(__('Please fill out the billing company', 'woocommerce-pakkelabels'));
} else {
wc_add_notice( __('Please fill out the billing company', 'woocommerce-pakkelabels') , 'error');
}
}
}
function pakkelabels_shipping_gls_business_show_below_shipping($rate){
global $woocommerce;
global $woocommerce;
$choosen_shipping_method1 = preg_replace('/\d/', '', $woocommerce->session->chosen_shipping_methods[0] );
$choosen_shipping_method2 = preg_replace('/\d/', '', $woocommerce->session->chosen_shipping_methods );
if($choosen_shipping_method1 == "legacy_pakkelabels_shipping_gls_business" || $choosen_shipping_method2 == "legacy_pakkelabels_shipping_gls_business"){
if($rate->method_id == 'legacy_pakkelabels_shipping_gls_business'){
echo '<div class="gls_shipping_method_text shipping_company_required">' . __('The company name is required.', 'woocommerce-pakkelabels').'</div>';
}
}
}
/* Register the shipping method in WooCommerce*/
function register_shipping_method($methods)
{
$methods['legacy_pakkelabels_shipping_gls_business'] = 'Legacy_Pakkelabels_Shipping_GLS_Business';
return $methods;
}
}
$pakkelabels_GLS_Business_Legacy = new Legacy_Pakkelabels_Shipping_GLS_Business();
$pakkelabels_GLS_Business_Legacy->mainAddActions();
$pakkelabels_GLS_Business_Legacy->addActions();
$pakkelabels_GLS_Business_Legacy->addFilters();
The plugin used is a delivery plugin, and since we're delivering to companies it requires a company name. However, since we are a B2B store we already have these company names registered and we do not want them nor need them in the checkout. So we have hidden the company name field in WooCommerce, but no matter what code we write we cannot make it not require it to be filled out.
Try the filter woocommerce_default_address_fields instead.
function modify_woocommerce_default_address_fields( $fields ) {
$fields['company']['required'] = false;
return $fields;
}
add_filter( 'woocommerce_default_address_fields', 'modify_woocommerce_default_address_fields', 100, 1 );
It states this in the documentation that there are specific fields that must be manipulated through this filter.
country
first_name
last_name
company
address_1
address_2
city
state
postcode
We can use a filter to remove the notice before it is added to the array specific just to that error message.
function modify_woocommerce_notices( $message ) {
if( stripos( $message, 'Please fill out the billing company' ) !== false ) {
return '';
}
}
add_filter( 'woocommerce_add_error', 'modify_woocommerce_notices' );
I haven't tested that code but that's the general idea of how you would suppress the error and prevent the required field for the billing company.

Is there a filter or hook t change the WC_Tax::get_rate_label( $key ) in woocommerce?

I am trying to change the Tax label on the cart, checkout order-review and email.
I have tried to create a function with 'woocommerce_get_order_item_totals' and also with 'woocommerce_get_formatted_order_total' No luck. It either remove all or adds a new line but changing the $tax_totals[ $code ]->label
I have a checkbox which gives customers to possibility to apply Tax-exempt for the order. This is all working very good.
If selected it will set TAX Amount to 0.00 but the label keeps on VAT or TAX or BTW (Dutch label)
I added zero-rates in the backend,
Phrase matches used to identify VAT (VAT, V.A.T, IVA, I.V.A., Value Added Tax, TVA, T.V.A., BTW, B.T.W., Tax Exempt, vrijgesteld van BTW)
I added zero-rate by country code
GB Tax Exempt (0%)
NL vrijgesteld van BTW (0%)
And still it shows on the cart, checkout, order-review and email as VAT or(BTW) whatever the country is.
This is what I want to change
I have been looking already for days to find a working solution with no luck.
But I found a solution just now, not sure if it is a hack or good coding but it works for me.
I have this code inside my function.
add_action( woocommerce_checkout_update_order_review','taxexempt_checkout_based_on_checkbox');
function taxexempt_checkout_based_on_checkbox( $post_data) {
global $woocommerce;
$woocommerce->customer->set_is_vat_exempt( false );
parse_str($post_data);
if ( $billing_taxexempt === '1' && $billing_confirmed === '1' &&
!empty($billing_signature) && ! empty($billing_declaration)){
$woocommerce->customer->set_is_vat_exempt( true );
}
}
This will apply the tax-exempt to the order.
I added a filter to this just below ....set_is_vat_exempt( true )..
add_filter( 'woocommerce_countries_tax_or_vat', function () { return __( 'Tax Exempt', 'woocommerce' ); });
And I added a function I found //Change "Billing Details" text to "Shipping Details" on Woocommerce checkout page
I changed it a little bit but it works for me.
function wc_change_field_strings( $translated_text, $text, $domain ) {
$language = get_locale();
$domain = 'woocommerce';
if($language == 'en_GB' ){
switch ( $translated_text ) {
case 'Tax Exempt' :
$translated_text = __( 'Tax Exempt', $domain );
break;
}
return $translated_text;
}
if($language == 'nl_NL' ){
switch ( $translated_text ) {
case 'Tax Exempt' :
$translated_text = __( 'vrijgesteld van BTW', $domain);
break;
}
return $translated_text;
}
}
add_filter( 'gettext', 'wc_change_field_strings', 20, 3 );
Have to add the default case, will do later but it works for, this solution.
Maybe it will work for somebody else or if you have a better solution, let me know.
And the result looks like this.

Gravity Forms Multi Page Losing POST value

I have a complex Gravity Form built, it has 10 pages. I am using fields to build a "string" that I then match to a CPT name to get meta data from to display a selection, based on user choices in the form.
One field I have is not holding its value in POST. I can see it when I select the value on the page, then when I click to next page the value is still there. However, after two pages the value ( and field ) disappear from POST.
This is the function I have put together that builds my product string.
add_filter( 'gform_pre_render_12', 'display_choice_result' );
function display_choice_result( $form ) {
$current_page = GFFormDisplay::get_current_page( $form['id'] );
$html_content = "";
$prod_string = "";
if ( $current_page >= 10 ) {
foreach ( $form['fields'] as &$field ) {
// Check for a class of "product-builder-item" on the field
// I use this as another way to denote what fields to add to string
if ( strpos( $field->cssClass, 'product-builder-item' ) === false ) {
continue;
}
//gather form data to save into html field (Field ID 14 on Form ID 12)
//exclude page break and any hidden fields
if ( $field->id != 14 && $field->type != 'page' ) {
$is_hidden = RGFormsModel::is_field_hidden( $form, $field, array() );
$populated = rgpost( 'input_' . $field->id );
// Make sure the field we are getting the value from is not hidden and has a value
if ( !$is_hidden && $populated !='' ) {
$html_content .= '<li>' . $field->label . ': ' . rgpost( 'input_' . $field->id ) . '</li>';
$prod_string .= rgpost( 'input_' . $field->id );
}
}
}
// Do a bunch of stuff here with the $prod_string variable
// ...
// ...
// ...
}
return $form;
}
Screenshots showing the POST disappearing..The POST field in question is input_22 with a value of 18000
This is one page after I choose from the field
This is two pages after,
Anyone run into this before or have any idea why it would be disappearing?
Thank you.
I was having the same exact issue as you described. I realized that a jQuery function was interfering with Gravity Form process. The jQuery function was set to change a zip code field from type text to tel so the number pad would open up on mobile devices. This is what was causing my issue.