Create a new shipping method in woocommerce 3 - php

I need help in generating new shipping method in woocommerce version 3+. The name for new field is "Nextday delivery". Like the flat rate it also need to be there in the method but it was not displayed in the drop down select field.
The below is the code which I tried. But it's not working for me.
function request_a_shipping_quote_init() {
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends WC_Shipping_Method {
public function __construct() {
$this->id = 'request_a_shipping_quote'; // Id for your shipping method. Should be uunique.
$this->method_title = __( 'Request a Shipping Quote' ); // Title shown in admin
$this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted' ); // Description shown in admin
$this->title = "Request a Shipping Quote"; // This can be added as an setting but for this example its forced.
$this->supports = array(
'shipping-zones'
);
$this->init();
}
function init() {
$this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
$this->init_settings(); // This is part of the settings API. Loads settings you previously init.
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'dc_raq' ),
'type' => 'checkbox',
'description' => __( 'Enable this shipping method.', 'dc_raq' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'dc_raq' ),
'type' => 'text',
'description' => __( 'Title to be displayed on site', 'dc_raq' ),
'default' => __( 'Request a Quote', 'dc_raq' )
),
);
}
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0.00',
'calc_tax' => 'per_item'
);
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
I need it to come in the dropdown like flatrate free shipping etc but it was not coming in the dropdown.

There were some missing things and others unnecessary. The correct way to make it work is:
add_action('woocommerce_shipping_init', 'request_shipping_quote_method');
function request_shipping_quote_method() {
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0) {
$this->id = 'request_shipping_quote';
$this->instance_id = absint( $instance_id );
$this->domain = 'rasq';
$this->method_title = __( 'Request a Shipping Quote', $this->domain );
$this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted', $this->domain );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
## Load the settings API
function init() {
$this->init_form_fields();
$this->init_settings();
$this->enabled = $this->get_option( 'enabled', $this->domain );
$this->title = $this->get_option( 'title', $this->domain );
$this->info = $this->get_option( 'info', $this->domain );
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
function init_form_fields() {
$this->instance_form_fields = array(
'title' => array(
'type' => 'text',
'title' => __('Title', $this->domain),
'description' => __( 'Title to be displayed on site.', $this->domain ),
'default' => __( 'Request a Quote ', $this->domain ),
),
'cost' => array(
'type' => 'text',
'title' => __('Coast', $this->domain),
'description' => __( 'Enter a cost', $this->domain ),
'default' => '',
),
);
}
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0',
'calc_tax' => 'per_item'
);
$this->add_rate( $rate );
}
}
}
}
add_filter('woocommerce_shipping_methods', 'add_request_shipping_quote');
function add_request_shipping_quote( $methods ) {
$methods['request_shipping_quote'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
Code goes in function.php file of your active child theme (active theme).
Tested and works.
Here the shipping method selector now displays this "Request a shipping coast" method:
Once selected and added, it's created this time:
If you edit it:

Related

Custom WooCommerce Shipping Method

I have this working code which generating and saving properly a custom shipping method under woocommerce setting > shipping zones.
My problem is that I can't make the shipping method show on the checkout page.
Any help on how to resolve this issue and maybe extend the code a bit would be greatly appreciated.
add_filter('woocommerce_shipping_methods', 'add_local_shipping');
function add_local_shipping($methods) {
$methods['local_shipping'] = 'Local_Shipping_Method';
return $methods;
}
class Local_Shipping_Method extends WC_Shipping_Method {
public function __construct($instance_id = 0) {
$this->id = 'local_shipping';
$this->instance_id = absint($instance_id);
$this->domain = 'local_shipping';
$this->method_title = __('Pickup', $this->domain);
$this->method_description = __('Pickup Location for WooCommerce', $this->domain);
$this->title = __('Pickup Location', $this->domain);
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable' ),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method' ),
'default' => 'yes',
),
'title' => array(
'title' => __( 'Method Title' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.' ),
'default' => __( 'Pickup Location' ),
'desc_tip' => true
),
'tax_status' => array(
'title' => __( 'Tax status', 'woocommerce' ),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'taxable',
'options' => array(
'taxable' => __( 'Taxable', 'woocommerce' ),
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
),
),
'cost' => array(
'title' => __( 'Cost', 'woocommerce' ),
'type' => 'text',
'placeholder' => '0',
'description' => __( 'Optional cost for pickup.', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
);
$this->enabled = $this->get_option( 'enabled' );
$this->title = __('Pickup Location', $this->domain);
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'id' => $this->id . $this->instance_id,
'label' => $this->title,
'cost' => 0,
) );
}
}
The way you have tried it is wrong. And it's not recommended to keep the text domain in a variable or a method.
To Create a Custom Shipping Method You have to follow these steps I have corrected on your code.
Hope this helps. You can learn more about how to create new shipping method here. Feel free
// To initialize your new shipping method you have to keep it in function
function local_shipping_init() {
if ( ! class_exists( Local_Shipping_Method ) ) {
class Local_Shipping_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$this->id = 'local_shipping';
$this->instance_id = absint( $instance_id );
$this->method_title = __( 'Pickup', 'text-domain' );
$this->method_description = __( 'Pickup Location for WooCommerce', 'text-domain' );
$this->title = __( 'Pickup Location', 'text-domain' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
// then you have to call this method to initiate your settings
$this->init();
}
public function init() {
// this method used to initiate your fields on settings
$this->init_form_fields();
// this is settings instance where you can declar your settings field
$this->init_instance_settings();
// user defined values goes here, not in construct
$this->enabled = $this->get_option( 'enabled' );
$this->title = __( 'Pickup Location', 'text-domain' );
// call this action in init() method to save your settings at the backend
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
public function init_instance_settings() {
// you have to keep all the instance settings field inside the init_instance_settings method
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable' ),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method' ),
'default' => 'yes',
),
'title' => array(
'title' => __( 'Method Title' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.' ),
'default' => __( 'Pickup Location' ),
'desc_tip' => true
),
'tax_status' => array(
'title' => __( 'Tax status', 'woocommerce' ),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'taxable',
'options' => array(
'taxable' => __( 'Taxable', 'woocommerce' ),
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
),
),
'cost' => array(
'title' => __( 'Cost', 'woocommerce' ),
'type' => 'text',
'placeholder' => '0',
'description' => __( 'Optional cost for pickup.', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
);
}
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'id' => $this->id, // you should define only your shipping method id here
'label' => $this->title,
'cost' => 0,
) );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'local_shipping_init' ); // use this hook to initialize your new custom method
function add_local_shipping( $methods ) {
$methods['local_shipping'] = 'Local_Shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'add_local_shipping' );
The code is tested and works fine. See the screenshot below.

Problem with foreach array on select option on woocmmerce function class

I create a function to add different shiping prices foreach user, all works fine for only one user (the first on the list), but i can't get to make the select options foreach user, it only shows 1 option with all the user in it.
the problem is integrate the foreach in here: 'test' => array. It creates the html elemnt but only 1 and not 1 foreach user
my code:
class WC_Shipping_click extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$args = array(
'role' => '',
'orderby' => 'user_nicename',
'order' => 'ASC'
);
$users = get_users( $args );
foreach ( $users as $user ){
$userinfo .= '['.$user->precio.','.$user->first_name.'] ';
}
$this->id = 'click_method';
$this->instance_id = absint( $instance_id );
$this->method_title = __( 'Click Shipping Method' );
$this->method_description = __( 'Click Shipping' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable' ),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method' ),
'default' => 'yes',
),
'test' => array(
'title' => __( 'Prueba de array' ),
'description' => $user->first_name,
'type' => 'select',
'options' => array( ''.$userinfo.'' => ''.$userinfo'',),
'label' => __( 'Some field' ),
'required' => true,
)
)
);
$this->enabled = $this->get_option( 'enabled' );
$this->prueba = $this->get_option( 'prueba' );
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* #param array $package (default: array())
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'id' => $this->id . $this->instance_id,
'label' => $this->title,
'cost' => $this->test,
) );
}
}
This is the scope of your foreach()
foreach ( $users as $user ){
$userinfo .= '['.$user->precio.','.$user->first_name.'] ';
}
Nothing that is below will fall into this foreach() loop.

Insert Checkbox on WooCommerce general settings page for purchase filter

I am trying to create a an extra option on the General settings WooCommerce page but could not get that working so I tried with the advanced tab instead, which seem to work.
The goal here is to create a checkbox option which enables a catalog mode by applying the filter for is_purchasable.
But, what I cannot figure out is how to apply and save the filter for woocommerce_is_purchasable if the checkbox is marked the settings saved.
Here's what I got so far:
add_filter( 'woocommerce_get_sections_advanced', 'catalog_mode_add_section' );
add_filter( 'woocommerce_get_settings_advanced', 'catalog_mode_all_settings', 10, 2 );
function catalog_mode_add_section( $sections ) {
$sections['catalog-mode'] = __( 'Catalog Mode', 'text-domain' );
return $sections;
}
function catalog_mode_all_settings( $settings, $current_section ) {
if ( $current_section == 'catalog-mode' ) {
$settings_catalog_options = array();
// Add Title to the Settings
$settings_catalog_options[] = array( 'name' => __( 'WooCommerce Catalog Mode', 'text-domain' ), 'type' => 'title', 'desc' => __( 'This turns WooCommerce into a catalog.', 'text-domain' ), 'id' => 'catalog_mode' );
// Add second text field option
$settings_catalog_options[] = array(
'name' => __( 'Catalog Mode', 'text-domain' ),
'id' => 'catalog_mode',
'type' => 'checkbox',
);
$settings_catalog_options[] = array( 'type' => 'sectionend', 'id' => 'catalog_mode' );
return $settings_catalog_options;
} else {
return $settings;
}
}
I'm lost right now..
Anyone?
There is a little mistake in your code, where each setting component need a unique identifier (id)… I have updated your code and your custom option is now saved.
add_filter( 'woocommerce_get_sections_advanced', 'catalog_mode_add_section' );
function catalog_mode_add_section( $sections ) {
$sections['catalog-mode'] = __( 'Catalog Mode', 'text-domain' );
return $sections;
}
add_filter( 'woocommerce_get_settings_advanced', 'catalog_mode_all_settings', 10, 2 );
function catalog_mode_all_settings( $settings, $current_section ) {
if ( $current_section == 'catalog-mode' ) {
$settings_catalog_options = array();
// Add Title to the Settings
$settings_catalog_options[] = array(
'name' => __( 'WooCommerce Catalog Mode', 'text-domain' ),
'type' => 'title',
'desc' => __( 'This turns WooCommerce into a catalog.', 'text-domain' ),
'id' => 'wc_catalog_mode_title'
);
// Add second text field option
$settings_catalog_options[] = array(
'name' => __( 'Catalog Mode', 'text-domain' ),
'type' => 'checkbox',
'id' => 'wc_catalog_mode',
);
$settings_catalog_options[] = array(
'type' => 'sectionend',
'id' => 'wc_catalog_mode_end'
);
return $settings_catalog_options;
}
return $settings;
}
Then in woocommerce_is_purchasable and woocommerce_variation_is_purchasable filters, you will use it this way:
add_filter('woocommerce_is_purchasable', 'product_is_purchasable_filter_callback', 10, 2 );
add_filter( 'woocommerce_variation_is_purchasable', 'product_is_purchasable_filter_callback', 10, 2 );
function product_is_purchasable_filter_callback( $purchasable, $product ) {
if( 'yes' === get_option('wc_catalog_mode') ) {
$purchasable = false;
}
return $purchasable;
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
You could use "products" section instead of "advanced" replacing your hooks with:
woocommerce_get_sections_products
woocommerce_get_settings_products

Add a custom payment gateway with additional radio buttons in Woocommerce

I am developing a custom payment method for woocommerce follogin is my code :
class WC_Gateway_Custom extends WC_Payment_Gateway {
public $domain;
/**
* Constructor for the gateway.
*/
public function __construct() {
$this->domain = 'custom_payment';
$this->id = 'custom';
$this->icon = apply_filters('woocommerce_custom_gateway_icon', '');
$this->has_fields = false;
$this->method_title = __( 'Custom', $this->domain );
$this->method_description = __( 'Allows payments with custom gateway.', $this->domain );
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions', $this->description );
$this->order_status = $this->get_option( 'order_status', 'completed' );
// Actions
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_thankyou_custom', array( $this, 'thankyou_page' ) );
// Customer Emails
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
}
/**
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', $this->domain ),
'type' => 'checkbox',
'label' => __( 'Enable Custom Payment', $this->domain ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', $this->domain ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', $this->domain ),
'default' => __( 'Custom Payment', $this->domain ),
'desc_tip' => true,
),
'order_status' => array(
'title' => __( 'Order Status', $this->domain ),
'type' => 'select',
'class' => 'wc-enhanced-select',
'description' => __( 'Choose whether status you wish after checkout.', $this->domain ),
'default' => 'wc-completed',
'desc_tip' => true,
'options' => wc_get_order_statuses()
),
'description' => array(
'title' => __( 'Description', $this->domain ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', $this->domain ),
'default' => __('Payment Information', $this->domain),
'desc_tip' => true,
),
'instructions' => array(
'title' => __( 'Instructions', $this->domain ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page and emails.', $this->domain ),
'default' => '',
'desc_tip' => true,
),
);
}
/**
* Output for the order received page.
*/
public function thankyou_page() {
if ( $this->instructions )
echo wpautop( wptexturize( $this->instructions ) );
}
/**
* Add content to the WC emails.
*
* #access public
* #param WC_Order $order
* #param bool $sent_to_admin
* #param bool $plain_text
*/
public function payment_fields(){
if ( $description = $this->get_description() ) {
echo wpautop( wptexturize( $description ) );
}
echo 'added custom field in radio buttons';
/**
* Process the payment and return the result.
*
* #param int $order_id
* #return array
*/
}
public function generate_form($order_id){
global $woocommerce;
// Get this Order's information so that we know
// who to charge and how much
$customer_order = new WC_Order($order_id);
$_instructions = $this->instructions;
$_order_status = $this->order_status;
$items = $customer_order->get_items();
$product_name = array();
foreach ( $items as $item ) {
array_push($product_name, $item['name']);
}
$_Description = implode(", ", $product_name);
echo 'here i want to get the value selected by the customer from front end';
//here is the part where i want to get the value of form inside payment_fields() fucntion
exit;
}
}
i need to set transaction type of my custom payment method attaching screen shot as well for better understanding, see:
there is no help on how to over ride this payment_fields() function i can get the html printed but don't have any idea how to get the value and set it as transaction type of the order
There is some errors, mistakes and missing things in your code… Here is a complete plugin file that works adding to this "Special" payment radio buttons on the gateway when it's selected in checkout page.
The selected "Transaction type" radio button value will be saved in the order as custom meta data.
The selected "Transaction type" value will be displayed in:
Order recieved page, My account > View Order
Admin Edit order pages
On the email notifications
On Order view page:
Here is the complete plugin code:
<?php
/**
* Plugin Name: WooCommerce Special Payment Gateway
* Plugin URI:
* Description: custom Special payment method.
* Author: Me
* Author URI: http://www.something.tld/
* Version: 1.1.0
* Text Domain: wcpg-special
* Domain Path: /i18n/languages/
*
* Copyright: (c) 2018
*
* License: GNU General Public License v3.0
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
*
* #package wcpg-special
* #author Me
* #category Admin
* #copyright Copyright (c) 2016-2018
* #license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
*/
defined( 'ABSPATH' ) or exit;
// Make sure WooCommerce is active
if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
return;
}
/**
* Add the gateway to WC Available Gateways
*
* #since 1.0.0
* #param array $gateways all available WC gateways
* #return array $gateways all WC gateways + Custom Special gateway
*/
function wc_add_special_to_gateways( $gateways ) {
$gateways[] = 'WC_Gateway_Special';
return $gateways;
}
add_filter( 'woocommerce_payment_gateways', 'wc_add_special_to_gateways' );
/**
* Adds plugin page links
*
* #since 1.0.0
* #param array $links all plugin links
* #return array $links all plugin links + our custom links (i.e., "Settings")
*/
function wc_special_gateway_plugin_links( $links ) {
$plugin_links = array(
'' . __( 'Configure', 'wcpg-special' ) . ''
);
return array_merge( $plugin_links, $links );
}
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'wc_special_gateway_plugin_links' );
/**
* Custom Payment Gateway
*
* Provides an Custom Payment Gateway; mainly for testing purposes.
* We load it later to ensure WC is loaded first since we're extending it.
*
* #class WC_Gateway_Special
* #extends WC_Payment_Gateway
* #version 1.0.0
* #package WooCommerce/Classes/Payment
* #author Me
*/
add_action( 'plugins_loaded', 'wc_special_gateway_init', 11 );
function wc_special_gateway_init() {
class WC_Gateway_Special extends WC_Payment_Gateway {
public $domain;
/**
* Constructor for the gateway.
*/
public function __construct() {
$this->id = 'special_payment';
$this->domain = 'wcpg-special';
$this->icon = apply_filters('woocommerce_payment_gateway_icon', '');
$this->has_fields = false;
$this->method_title = __( 'Custom Payment', $this->domain );
// Define "payment type" radio buttons options field
$this->options = array(
'type1' => __( 'Type 1', $this->domain ),
'type2' => __( 'Type 2', $this->domain ),
'type3' => __( 'Type 3', $this->domain ),
);
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions' );
$this->order_status = $this->get_option( 'order_status' );
$this->status_text = $this->get_option( 'status_text' );
// Actions
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_checkout_create_order', array( $this, 'save_order_payment_type_meta_data' ), 10, 2 );
add_filter( 'woocommerce_get_order_item_totals', array( $this, 'display_transaction_type_order_item_totals'), 10, 3 );
add_action( 'woocommerce_admin_order_data_after_billing_address', array( $this, 'display_payment_type_order_edit_pages'), 10, 1 );
add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) );
// Customer Emails
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
}
/**
* Initialize Gateway Settings Form Fields
*/
public function init_form_fields() {
$this->form_fields = apply_filters( 'wc_special_payment_form_fields', array(
'enabled' => array(
'title' => __( 'Enable/Disable', $this->domain ),
'type' => 'checkbox',
'label' => __( 'Enable Special Payment', $this->domain ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', $this->domain ),
'type' => 'text',
'description' => __( 'This controls the title for the payment method the customer sees during checkout.', $this->domain ),
'default' => __( 'Special Payment', $this->domain ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Description', $this->domain ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', $this->domain ),
'default' => __( 'Please remit payment to Store Name upon pickup or delivery.', $this->domain ),
'desc_tip' => true,
),
'instructions' => array(
'title' => __( 'Instructions', $this->domain ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page and emails.', $this->domain ),
'default' => '', // Empty by default
'desc_tip' => true,
),
'order_status' => array(
'title' => __( 'Order Status', $this->domain ),
'type' => 'select',
'description' => __( 'Choose whether order status you wish after checkout.', $this->domain ),
'default' => 'wc-completed',
'desc_tip' => true,
'class' => 'wc-enhanced-select',
'options' => wc_get_order_statuses()
),
'status_text' => array(
'title' => __( 'Order Status Text', $this->domain ),
'type' => 'text',
'description' => __( 'Set the text for the selected order status.', $this->domain ),
'default' => __( 'Order is completed', $this->domain ),
'desc_tip' => true,
),
) );
}
/**
* Output the "payment type" radio buttons fields in checkout.
*/
public function payment_fields(){
if ( $description = $this->get_description() ) {
echo wpautop( wptexturize( $description ) );
}
echo '<style>#transaction_type_field label.radio { display:inline-block; margin:0 .8em 0 .4em}</style>';
$option_keys = array_keys($this->options);
woocommerce_form_field( 'transaction_type', array(
'type' => 'radio',
'class' => array('transaction_type form-row-wide'),
'label' => __('Payment Information', $this->domain),
'options' => $this->options,
), reset( $option_keys ) );
}
/**
* Save the chosen payment type as order meta data.
*
* #param object $order
* #param array $data
*/
public function save_order_payment_type_meta_data( $order, $data ) {
if ( $data['payment_method'] === $this->id && isset($_POST['transaction_type']) )
$order->update_meta_data('_transaction_type', esc_attr($_POST['transaction_type']) );
}
/**
* Output for the order received page.
*
* #param int $order_id
*/
public function thankyou_page( $order_id ) {
$order = wc_get_order( $order_id );
if ( $this->instructions ) {
echo wpautop( wptexturize( $this->instructions ) );
}
}
/**
* Display the chosen payment type on the order edit pages (backend)
*
* #param object $order
*/
public function display_payment_type_order_edit_pages( $order ){
if( $this->id === $order->get_payment_method() && $order->get_meta('_transaction_type') ) {
$options = $this->options;
echo '<p><strong>'.__('Transaction type').':</strong> ' . $options[$order->get_meta('_transaction_type')] . '</p>';
}
}
/**
* Display the chosen payment type on order totals table
*
* #param array $total_rows
* #param WC_Order $order
* #param bool $tax_display
* #return array
*/
public function display_transaction_type_order_item_totals( $total_rows, $order, $tax_display ){
if( is_a( $order, 'WC_Order' ) && $order->get_meta('_transaction_type') ) {
$new_rows = []; // Initializing
$options = $this->options;
// Loop through order total lines
foreach( $total_rows as $total_key => $total_values ) {
$new_rows[$total_key] = $total_values;
if( $total_key === 'payment_method' ) {
$new_rows['payment_type'] = [
'label' => __("Transaction type", $this->domain) . ':',
'value' => $options[$order->get_meta('_transaction_type')],
];
}
}
$total_rows = $new_rows;
}
return $total_rows;
}
/**
* Add content to the WC emails.
*
* #access public
* #param WC_Order $order
* #param bool $sent_to_admin
* #param bool $plain_text
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( $this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method()
&& $order->has_status( $this->order_status ) ) {
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
}
}
/**
* Process the payment and return the result
*
* #param int $order_id
* #return array
*/
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
// Mark as on-hold (we're awaiting the payment)
$order->update_status( $this->order_status, $this->status_text );
// Reduce stock levels
wc_reduce_stock_levels( $order->get_id() );
// Remove cart
WC()->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
}
}
Code goes in as plugin php file that you can name as you want (and include it optionally in a folder). Zip the file (or the folder) and add it as a plugin via Wordpress. Activate it.
Tested and works.
On Email notifications:

WooCommerce - disable BACS for one shipping method

I would like to disable wire transfer payment method (bacs gateway) for a specific shipping method. I want customers to pay for the shipping if they select Cash on Delivery payment method but I want them also to get free shipping if they select wire transfer method.
I was able to disable COD if they select free shipping, but was not able to disable wire transfer if they select not-free shipping.
How can I disable BACS for that one particular shipping method?
I already had installed the WooCommerce Custom Payment Gateways plugin. That activates some more gateway options so I was working with it and edited one of it's classes.
The following is my modified version of woocommerce-custom-payment-gateways/class-wc-custom_payment_gateway_5.php
<?php
/**
* WC wcCpg5 Gateway Class.
* Built the wcCpg5 method.
*/
class WC_Custom_Payment_Gateway_5 extends WC_Gateway_BACS {
/**
* Constructor for the gateway.
*
* #return void
*/
public function __construct() {
global $woocommerce;
$this->id = 'wcCpg5';
$this->icon = apply_filters( 'woocommerce_wcCpg5_icon', '' );
$this->has_fields = false;
$this->method_title = __( 'Bacs', 'woocommerce' );
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->instructions = $this->get_option( 'instructions', $this->description );
$this->enable_for_methods = $this->get_option( 'enable_for_methods', array() );
// BACS account fields shown on the thanks page and in emails
$this->account_details = get_option( 'woocommerce_bacs_accounts',
array(
array(
'account_name' => $this->get_option( 'account_name' ),
'account_number' => $this->get_option( 'account_number' ),
'sort_code' => $this->get_option( 'sort_code' ),
'bank_name' => $this->get_option( 'bank_name' ),
'iban' => $this->get_option( 'iban' ),
'bic' => $this->get_option( 'bic' )
)
)
);
// Actions
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'save_account_details' ) );
add_action( 'woocommerce_thankyou_bacs', array( $this, 'thankyou_page' ) );
// Customer Emails
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
// Actions.
if ( version_compare( WOOCOMMERCE_VERSION, '2.0.0', '>=' ) )
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( &$this, 'process_admin_options' ) );
else
add_action( 'woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ) );
}
/* Admin Panel Options.*/
function admin_options() {
?>
<h3><?php _e('Custom Payment Gateways 5','wcwcCpg5'); ?></h3>
<table class="form-table">
<?php $this->generate_settings_html(); ?>
</table> <?php
}
/* Initialise Gateway Settings Form Fields. */
public function init_form_fields() {
$shipping_methods = array();
if ( is_admin() )
foreach ( WC()->shipping->load_shipping_methods() as $method ) {
$shipping_methods[ $method->id ] = $method->get_title();
}
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable Bank Transfer', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Direct Bank Transfer', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
'default' => __( 'Make your payment directly into our bank account. Please use your Order ID as the payment reference. Your order won\'t be shipped until the funds have cleared in our account.', 'woocommerce' ),
'desc_tip' => true,
),
'instructions' => array(
'title' => __( 'Instructions', 'woocommerce' ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page and emails.', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
'account_details' => array(
'type' => 'account_details'
),
'enable_for_methods' => array(
'title' => __( 'Enable for shipping methods', 'woocommerce' ),
'type' => 'multiselect',
'class' => 'chosen_select',
'css' => 'width: 450px;',
'default' => '',
'description' => __( 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce' ),
'options' => $shipping_methods,
'desc_tip' => true,
'custom_attributes' => array(
'data-placeholder' => __( 'Select shipping methods', 'woocommerce' )
)
)
);
}
/**
* Check If The Gateway Is Available For Use
*
* #return bool
*/
public function is_available() {
$order = null;
if ( ! $this->enable_for_virtual ) {
if ( WC()->cart && ! WC()->cart->needs_shipping() ) {
return false;
}
if ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) {
$order_id = absint( get_query_var( 'order-pay' ) );
$order = wc_get_order( $order_id );
// Test if order needs shipping.
$needs_shipping = false;
if ( 0 < sizeof( $order->get_items() ) ) {
foreach ( $order->get_items() as $item ) {
$_product = $order->get_product_from_item( $item );
if ( $_product->needs_shipping() ) {
$needs_shipping = true;
break;
}
}
}
$needs_shipping = apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping );
if ( $needs_shipping ) {
return false;
}
}
}
if ( ! empty( $this->enable_for_methods ) ) {
// Only apply if all packages are being shipped via local pickup
$chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' );
if ( isset( $chosen_shipping_methods_session ) ) {
$chosen_shipping_methods = array_unique( $chosen_shipping_methods_session );
} else {
$chosen_shipping_methods = array();
}
$check_method = false;
if ( is_object( $order ) ) {
if ( $order->shipping_method ) {
$check_method = $order->shipping_method;
}
} elseif ( empty( $chosen_shipping_methods ) || sizeof( $chosen_shipping_methods ) > 1 ) {
$check_method = false;
} elseif ( sizeof( $chosen_shipping_methods ) == 1 ) {
$check_method = $chosen_shipping_methods[0];
}
if ( ! $check_method ) {
return false;
}
$found = false;
foreach ( $this->enable_for_methods as $method_id ) {
if ( strpos( $check_method, $method_id ) === 0 ) {
$found = true;
break;
}
}
if ( ! $found ) {
return false;
}
}
return parent::is_available();
}
}
with this you have the option to enable bacs for shipping methods

Categories