EDITED - Progress made on original post
I have created a simple custom shipping method plugin stub (see code below).
The plugin is registered and now appears in the shipping method dropdown when I'm creating a shipping zone. However when selected the custom field doesn't appear for the shipping zone (see gif)
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
function launch_shipping_method() {
if (!class_exists('Launch_Shipping_Method')) {
class Launch_Shipping_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$this->id = 'launch_shipping';
$this->instance_id = absint( $instance_id );
$this->method_title = __('Launch Simple Shipping', 'launch_shipping');
$this->method_description = __('Custom Simple Shipping Method', 'launch_shipping');
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Initialize Launch Simple Shipping.
*/
public function init() {
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables.
$this->title = isset($this->settings['title']) ? $this->settings['title'] : __('Launch Shipping', 'launch_shipping');
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
/**
* Init form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'title' => array(
'title' => __( 'Title', 'launch_shipping' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'launch_shipping' ),
'default' => $this->method_title,
'desc_tip' => true,
)
);
}
/**
* Get setting form fields for instances of this shipping method within zones.
*
* #return array
*/
public function get_instance_form_fields() {
return parent::get_instance_form_fields();
}
/**
* Always return shipping method is available
*
* #param array $package Shipping package.
* #return bool
*/
public function is_available( $package ) {
$is_available = true;
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
}
/**
* Free shipping rate applied for this method.
*
* #uses WC_Shipping_Method::add_rate()
*
* #param array $package Shipping package.
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate(
array(
'label' => $this->title,
'cost' => 0,
'taxes' => false,
'package' => $package,
)
);
}
}
}
}
add_action('woocommerce_shipping_init', 'Launch_Shipping_Method');
function add_launch_shipping_method($methods) {
$methods[] = 'launch_shipping_method';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_launch_shipping_method');
}
Try this:
function add_launch_shipping_method($methods) {
$methods['launch_shipping'] = 'launch_shipping_method';
return $methods;
}
It should fix things. If you need to debug it or want to understand more have a look at:
wp-content/plugins/woocommerce/includes/class-wc-shipping-zone.php
look at
function add_shipping_method($type)
Briefly: the id you register the class with in your woocommerce_shipping_init hook must match the class id property (the one you set with $this->id = 'launch_shipping';)
Related
I'm working on a custom plugin that processes order data & sends it to another Web application.
I hook in to order processing using WooCommerce's woocommerce_checkout_order_processed hook, so, I get the order id as an argument & hence can easily obtain WC_Order.
The problem I got stuck with is the following:
I want to calculate some data based on the shipping method chosen by the customer, but I need more data than just the shipping method name in order to perform the calculation.
A simplified version of what I want to achieve is essentially something very similar to:
$order = wc_get_order($order_id);
$is_express_shipping = strpos($order->get_shipping_method(), 'Express') !== false;
But the whole problem is that the shipping method name does not contain (and in fact, it should not) any hint regarding whether it is an express shipping method or not, so, the only option is to pass some additional information about the shipping method through.
I've tried to add a custom shipping method as described in this question & in its accepted answer, so, I added the desired data into shipping method settings like this:
But it looks like WooCommerce doesn't expect custom shipping classes to register custom fields or at least, I didn't figure out how to get the Launch Simple Shipping's "Shipping Mode" property from within the order object (it does not appear anywhere within $order->get_shipping_methods() output).
Here is the full code of the custom shipping class in case if needed. It's a copy-paste from the previously mentioned question + a new field.
function launch_shipping_method() {
if (!class_exists('Launch_Shipping_Method')) {
class Launch_Shipping_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$this->id = 'launch_shipping';
$this->instance_id = absint( $instance_id );
$this->method_title = __('Launch Simple Shipping', 'launch_shipping');
$this->method_description = __('Custom Simple Shipping Method', 'launch_shipping');
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Initialize Launch Simple Shipping.
*/
public function init() {
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables.
$this->title = isset($this->settings['title']) ? $this->settings['title'] : __('Launch Shipping', 'launch_shipping');
$this->shipping_mode = isset($this->settings['shipping_mode']) ? $this->settings['shipping_mode'] : __('Launch Shipping', 'launch_shipping');
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
/**
* Init form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'title' => array(
'title' => __( 'Title', 'launch_shipping' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'launch_shipping' ),
'default' => $this->method_title,
'desc_tip' => true,
),
'shipping_mode' => array(
'title' => __( 'Shipping Mode', 'launch_shipping' ),
'type' => 'select',
'default' => 'Standard',
'options' => [
'Standard' => 'Standard',
'Express' => 'Express',
],
)
);
}
/**
* Get setting form fields for instances of this shipping method within zones.
*
* #return array
*/
public function get_instance_form_fields() {
return parent::get_instance_form_fields();
}
/**
* Always return shipping method is available
*
* #param array $package Shipping package.
* #return bool
*/
public function is_available( $package ) {
$is_available = true;
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
}
/**
* Free shipping rate applied for this method.
*
* #uses WC_Shipping_Method::add_rate()
*
* #param array $package Shipping package.
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate(
array(
'label' => $this->title,
'cost' => 0,
'taxes' => false,
'package' => $package,
'shipping_mode' => $this->shipping_mode,
)
);
}
}
}
}
add_action('woocommerce_shipping_init', 'Launch_Shipping_Method');
function add_launch_shipping_method($methods) {
$methods['launch_shipping'] = 'launch_shipping_method';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_launch_shipping_method');
Is there a way to somehow pass additional data about the chosen shipping method into WC_Order object or somehow obtain it having WC_Order at hand?
I need to change the Woocommerce payment gateway names, not the ones hat are displayed on the frontend(this can easily be achieved in the settings) but the inernatl titles Woo is using.
In class-wc-gateway-cheque.php for example I found this
$this->id = 'cheque';
but simply changing the name there did not work. How can I change the name Woocommerce is using internally for this payment method?
So what you can do instead is to copy the source code from WC_Gateway_Cheque Class to a plugin file as explained below:
To make a custom gateway based on an existing WooCommerce payment method as cheque, It's recommended to copy the source code from WC_Gateway_Cheque Class in a plugin (adapting the code for your needs).
You can copy the code to a php file that you will name for example wc-invoice-payments.php.
The code to copy:
<?php
/**
* Plugin Name: WooCommerce Invoice Gateway
* Plugin URI:
* Description: Clones the "Cheque" gateway to create another custom payment method.
* Author: Your name
* Author URI: http://www.something.tld/
* Version: 1.0.0
* Text Domain: wc-invoice-gateway
* Domain Path: /i18n/languages/
*
* Copyright: (c) 2016-2018
*
* License: GNU General Public License v3.0
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
*
* #package wc-invoice-gateway
* #author Your name
* #category Admin
* #copyright Copyright (c) 2020
* #license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
*
* This "Invoice" gateway forks the WooCommerce core "Cheque" payment gateway to create another custom payment method.
*/
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 gateway
*/
function wc_invoice_add_to_gateways( $gateways ) {
$gateways[] = 'WC_Invoice_Gateway';
return $gateways;
}
add_filter( 'woocommerce_payment_gateways', 'wc_invoice_add_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_gateway_invoice_plugin_links( $links ) {
$plugin_links = array(
'' . __( 'Configure', 'wc-invoice-gateway' ) . ''
);
return array_merge( $plugin_links, $links );
}
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'wc_gateway_invoice_plugin_links' );
/**
* Invoice 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_Invoice_Gateway
* #extends WC_Payment_Gateway
* #version 1.0.0
*/
add_action( 'plugins_loaded', 'wc_invoice_gateway_init', 11 );
function wc_invoice_gateway_init() {
class WC_Invoice_Gateway extends WC_Payment_Gateway {
/**
* Constructor for the gateway.
*/
public function __construct() {
$this->id = 'invoice';
$this->domain = 'wc-invoice-gateway';
$this->method_title = _x( 'Invoice payments', 'Invoice payment method', $this->domain );
$this->icon = apply_filters( 'woocommerce_invoice_icon', '' );
$this->has_fields = false;
$this->method_description = __( 'Take payments in person via Invoice. This offline gateway can also be useful to test purchases.', $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' );
// Actions.
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_thankyou_invoice', 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 = array(
'enabled' => array(
'title' => __( 'Enable/Disable', $this->domain ),
'type' => 'checkbox',
'label' => __( 'Enable Invoice payments', $this->domain ),
'default' => 'no',
),
'title' => array(
'title' => __( 'Title', $this->domain ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', $this->domain ),
'default' => _x( 'Invoice', 'Invoice payment method', $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' => __( 'Receive an invoice...', $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 wp_kses_post( wpautop( wptexturize( $this->instructions ) ) );
}
}
/**
* Add content to the WC emails.
*
* #access public
* #param WC_Order $order Order object.
* #param bool $sent_to_admin Sent to admin.
* #param bool $plain_text Email format: plain text or HTML.
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( $this->instructions && ! $sent_to_admin && 'invoice' === $order->get_payment_method() && $order->has_status( 'on-hold' ) ) {
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
}
/**
* Process the payment and return the result.
*
* #param int $order_id Order ID.
* #return array
*/
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order->get_total() > 0 ) {
// Mark as on-hold (we're awaiting the invoice).
$order->update_status( apply_filters( 'woocommerce_invoice_process_payment_order_status', 'on-hold', $order ), _x( 'Awaiting Invoice payment', 'Invoice payment method', $this->domain ) );
} else {
$order->payment_complete();
}
// Remove cart.
WC()->cart->empty_cart();
// Return thankyou redirect.
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order ),
);
}
} // end \WC_Invoice_Gateway class
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Then enable WooCommerce Invoice Gateway plugin in admin.
Now in WooCommerce settings, Payments section, you can enable this payment gateway.
You can unset / remove original Cheque payment gateway changing the 1st function like:
add_filter( 'woocommerce_payment_gateways', 'wc_invoice_add_to_gateways' );
function wc_invoice_add_to_gateways( $gateways ) {
$gateways[] = 'WC_Invoice_Gateway';
unset($gateways['WC_Gateway_Cheque']; // Remove Cheque gateway
return $gateways;
}
It should work as expected.
Related: Extending WooCommerce COD payment gateway in a plugin
Initial answer:
As all payment gateways extend WC_Payment_Gateway Class, if you look to get_title() method you will see that you can use the filter hook woocommerce_gateway_title.
So for "cheque" payment Id, you will use it as follow:
add_filter( 'woocommerce_gateway_title', 'change_cheque_payment_gateway_title', 100, 2 );
function change_cheque_payment_gateway_title( $title, $payment_id ){
if( $payment_id === 'cheque' ) {
$title = __("Something else", "woocommerce");
}
return $title;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
How to make shipping method based on weight for specific city?
For example, I want to take the postage for city "A" for $1 per kg.
Here is the code of plugin I made:
public function calculate_shipping( $package ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '10.99',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
Full code:
<?php
/*
Plugin Name: Trucking shipping
Plugin URI: http://abdhannan.com
Description: Trucking shipping dengan JNE dsb
Version: 1.0.0
Author: Abd Hannan
Author URI: http://abdhannan.com
*/
/**
* Check if WooCommerce is active
*/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function trucking_shipping_init() {
if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
class WC_trucking_shipping_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
public function __construct() {
$this->id = 'trucking_shipping_method'; // Id for your shipping method. Should be uunique.
$this->method_title = __( 'JNE TRUCKING' ); // Title shown in admin
$this->method_description = __( 'Pengiriman dengan truck JNE' ); // Description shown in admin
$this->enabled = "yes"; // This can be added as an setting but for this example its forced enabled
$this->title = "JNE TRUCKING"; // This can be added as an setting but for this example its forced.
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$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.
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* calculate_shipping function.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '10.99',
'calc_tax' => 'per_item'
);
// Register the rate
$this->add_rate( $rate );
}
}
}
}
add_action( 'woocommerce_shipping_init', 'trucking_shipping_init' );
function add_trucking_shipping_method( $methods ) {
$methods['trucking_shipping_method'] = 'WC_trucking_shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'add_trucking_shipping_method' );
}
The problem is in calculate_shipping, I don't know how to do what I want.
This is not really a code question, rather a 'how do I use WooCommerce' question. What you are looking for is functionality Automattic deliberately removed from WooCommerce so that they could charge for it, look here for the plugin.
If you are frugal and reduce your product weights down to a specific set, then all you really need is flat rate shipping assigned to postal code defined shipping zones, mixed with shipping classes and boom no programming ever needed.
Koda
I have successfully created a new shipping method and given it support for shipping zones. However when I come to select the method from the dropdown to add it to the zone it does not appear in the 'selected methods list'.
I recorded a screencast gif to demonstrate:
I can't for the life of me figure out why it's not working. It works fine if I select one of the standard methods (Screencast GIF)
Anyone know what's going on here and how to get it to work?
Here's the code that I have from this official thread: Shipping Method API:
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function request_a_shipping_quote_init() {
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends WC_Shipping_Method {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
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();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$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.
// Save settings in admin if you have any defined
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' )
),
);
}
/**
* calculate_shipping function.
*
* #access public
*
* #param mixed $package
*
* #return void
*/
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0.00',
'calc_tax' => 'per_item'
);
// Register the rate
$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' );
}
The method key on "woocommerce_shipping_methods" should match the shipping method id
In your case:
You should change
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' );
To:
function request_shipping_quote_shipping_method( $methods ) {
$methods['request_a_shipping_quote'] = 'WC_Request_Shipping_Quote_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
Change this line
public function calculate_shipping( $package ) {
to this line
public function calculate_shipping( $package = array() ) {
After I trying to use code in question and fix all errors that I found in comments to these post I still had some problems with it. For example I can't edit shipping method after even I successfully added it to shipping zone.
Finally I got desired code that working for me after edit standard free shipping woocoommerce method. Hope it will save time for someone.
function request_a_shipping_quote_init() {
if ( ! class_exists( 'Imp_WC_Shipping_Local_Pickup' ) ) {
class Imp_WC_Pickup_Shipping_Method extends WC_Shipping_Method {
/**
* Constructor.
*
* #param int $instance_id
*/
public function __construct( $instance_id = 0 ) {
$this->id = 'imp_pickup_shipping_method';
$this->instance_id = absint( $instance_id );
$this->method_title = __( "Самовывоз из точки выдачи ( MO г. Дзержинский )", 'imp' );
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Initialize custom shiping method.
*/
public function init() {
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( 'title' );
// Actions
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Calculate custom shipping method.
*
* #param array $package
*
* #return void
*/
public function calculate_shipping( $package = array() ) {
$this->add_rate( array(
'label' => $this->title,
'package' => $package,
) );
}
/**
* Init form fields.
*/
public function init_form_fields() {
$this->instance_form_fields = array(
'title' => array(
'title' => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
'desc_tip' => true,
),
);
}
}
}
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );
function request_shipping_quote_shipping_method( $methods ) {
$methods['imp_pickup_shipping_method'] = 'Imp_WC_Pickup_Shipping_Method';
return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
WC_Custom_Shipping_Method is an abstract class and you are trying to change its inherited method calculate_shipping which abstract classes don't allow.
Try doing it like this.
<?php
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
function request_a_shipping_quote_init() {
class Abs_Custom_Shipping extends WC_Shipping_Method{}
if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
class WC_Request_Shipping_Quote_Method extends Abs_Custom_Shipping {
/**
* Constructor for your shipping class
*
* #access public
* #return void
*/
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();
}
/**
* Init your settings
*
* #access public
* #return void
*/
function init() {
// Load the settings API
$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.
// Save settings in admin if you have any defined
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' )
),
);
}
/**
* calculate_shipping function.
*
* #access public
*
* #param mixed $package
*
* #return void
*/
public function calculate_shipping( $packages = array() ) {
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => '0.00',
'calc_tax' => 'per_item'
);
// Register the rate
$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' );
}
( extend the shipping method into a child class, then extend the child class into a grandchild class where you can modify the calculate_shipping method ).
Hope it makes sense.
Regards
I had this issue and it was driving me crazy for a few days until, while looking through the Woocommerce code to understand what was happening, I discovered that when setting up the filter method for the woocommerce_shipping_methods, I needed to make the index of the entry that I was adding to this array the same as the ID property in my shipping method class. Once I did this, it added the shipping method fine and it showed it correctly for the zone. Previously, I had been adding the entry to the array in the filter method with no index, which works fine as far as WC seeing the method which was why it seemed ok. However, the code that saves the settings, uses the ID as the index to identify the shipping method. From other comments, I would imagine that this specific index was added in WC version 3. Hope this helps.
If your shipping method still seems not to work, you have to ensure that
instance_id must be defined in constructor, as in this snippet
public function __construct($instance_id = 0)
{
$this->instance_id = absint($instance_id);
// other lines follow
}
there is no stale data: remove transient data and clients' data (WooCommerce Settings > Status > Tools)
Hi there, I'm trying to build a very simple plugin for woocommerce to show some information about delivery without taxes. The diference for the other methods is the extra HTML field.
I read a lot of the documentation but I think there is something miss on the configuration. The admin it seems working. But the method didn't appear on checkout screen. The code is below:
<?php
if ( ! defined( 'WPINC' ) ) {
die('security by preventing any direct access to your plugin file');
}
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
function shipping_delivery_info() {
if (!class_exists('shipping_delivery_info')) {
class shipping_delivery_info extends WC_Shipping_Method {
public function __construct( $instance_id = 0) {
$this->id = 'shipping_delivery_info';
$this->instance_id = absint( $instance_id );
$this->method_title = __('Shipping Delivery Info', 'shipping_delivery_info');
$this->method_description = __('A Woocommerce custom shipping method plugin, that shows ' .
'some shipping information to costumer, like free shipping but with HTML field.',
'shipping_delivery_info');
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
);
$this->init();
}
/**
* Load the settings API
*/
function init() {
// Load the settings
$this->init_form_fields();
$this->init_settings();
$this->enabled = $this->get_option( 'enabled' );
$this->title = $this->get_option( 'title' );
$this->info = $this->get_option( 'info' );
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
function init_form_fields() {
$this->instance_form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'shipping_delivery_info'),
'type' => 'checkbox',
'label' => __( 'Enable this shipping method', 'shipping_delivery_info'),
'default' => 'yes',
),
'title' => array(
'title' => __('Title', 'shipping_delivery_info'),
'type' => 'text',
'description' => __( 'The title to be displayed during checkout.', 'shipping_delivery_info' ),
'default' => __('Shipping Information', 'shipping_delivery_info'),
),
'info' => array(
'title' => __('Information', 'shipping_delivery_info'),
'type' => 'text',
'description' => __( 'Information about delivery and its taxes.', 'shipping_delivery_info' ),
'default' => __('Insert here some HTML.'),
),
);
}
}
}
}
add_action('woocommerce_shipping_init', 'shipping_delivery_info');
function add_shipping_delivery_info($methods)
{
$methods['shipping_delivery_info'] = 'shipping_delivery_info';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_shipping_delivery_info');
function shipping_delivery_info_message($posted)
{
$packages = WC()->shipping->get_packages();
$chosen_methods = WC()->session->get('chosen_shipping_methods');
if (is_array($chosen_methods) && in_array('shipping_delivery_info', $chosen_methods)) {
foreach ($packages as $i => $package) {
if ($chosen_methods[$i] != "shipping_delivery_info") {
continue;
}
$shipping_delivery_info = new shipping_delivery_info();
$message = $shipping_delivery_info->settings['info'];
return $message;
/*$messageType = "info";
wc_add_notice($message, $messageType);*/
}
}
}
add_action('woocommerce_review_order_before_cart_contents', 'shipping_delivery_info_message', 10);
add_action('woocommerce_after_checkout_validation', 'shipping_delivery_info_message', 10);
}
You need to add the calculate_shipping function to your class
/**
* function calculate_shipping.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package = array() ) {
$rate = array(
'id' => 'My Method id',
'label' => 'New method',
'cost' => 0,
'calc_tax' => 'per_item'
);
$this->add_rate( $rate );
}
}
Anyway, i think you don't need to add a new shipping method just to show some info at the cart, instead you can use these actions:
add_action( 'woocommerce_review_order_before_submit', 'add_tracking_notification', 12 );
add_action('woocommerce_proceed_to_checkout', 'add_tracking_notification');
function add_tracking_notification() {
echo '<h5 style="margin-bottom:10px">This is a custom message</h5>';
}