I'm working on a custom payment gateway for the WordPress plugin WooCommerce. I cannot seem to save the settings for the payment gateway. When I enter information into the fields and then click save, the page refreshes with all of the fields blank. What am I doing wrong?
Here is my code.
<?php
/**
* Plugin Name: Bitcoin WooCommerce Integration Made Easy
* Description: A Bitcoin processing plugin that integrates into WooCommerce made specifically for Bitcoin Publish.
* Version: 0.01
* Author: Cammy_the_block
*/
add_action( 'plugins_loaded', 'init_your_gateway_class' );
function init_your_gateway_class() {
class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {
function __construct() {
$this->id = "Bitcoin WooCommerce Integration Gateway";
$this->method_title = "Bitcoin with BWCIME";
$this->method_description = "More later";
$this->init_form_fields();
$this->init_settings();
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' ) );
}
}
function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable Cheque Payment', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Cheque Payment', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Customer Message', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
)
);
}
}
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$productArray = array();
$x = 0;
foreach( $order->get_items() as $item_id => $item ) {
$productArray[x] = $order->get_product_from_item( $item );
$x++;
}
// Mark as on-hold (we're awaiting the cheque)
$order->update_status('on-hold',
__( 'Awaiting cheque payment. there are ' + $productArray.length + 'items', 'woocommerce' )
);
// Remove cart
$woocommerce->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
}
function add_your_gateway_class ($methods ) {
$methods[] = 'WC_Gateway_Your_Gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
?>
EDIT:
The add filter code runs add_your_gateway_class, which in turn causes it to run WC_Gateway_Your_Gateway.
you have to call them on the constructor after the init_settings();
$this->init_settings();
// Define user set variables
$this->access_key = $this->get_option( 'access_key' );
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
edit:
you also need another action/hook, just at the end of the constructor, no need to create that new function that you came up with:
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
edit 2:
sorry you already have it, my bad :p, dont realy know what happened there, glad its solved
The actual problem is your this->id="example_gateway": id is always case sensitive and it should be without space and lowercase.
Example:
function __construct() {
$this->id = "bitcoin_woocommerce_integration_gateway";
$this->method_title =( "Bitcoin with BWCIME", 'bitcoin_woocommerce_integration_gateway' );
$this->title = __( "Bitcoin with BWCIME", 'bitcoin_woocommerce_integration_gateway' );
$this->method_description = "More later";
//further as same as your code.....
}
I'm not completely sure how I fixed it, but I believe it had to do with adding the function admin_options().
public function admin_options() {
?>
<h3><?php _e('Bitcoin Payment', 'woothemes'); ?></h3>
<p><?php _e('Message!.', 'woothemes'); ?></p>
<table class="form-table">
<?php
// Generate the HTML For the settings form.
$this->generate_settings_html();
?>
</table>
<?php
}
EDIT: I'm not sure what causes it but you have to clear the plugin's settings by interfacing with the database. The easy way to do this is to change the ID of the plugin. I'm not actually sure where the settings are stored in the database.
Related
I'm using the WC Vendors Woocommerce plugin that uses the following snippet in order to show 'Product Status' in vendors front-end dashboard:
/**
* Product status text for output on front end.
*/
public static function product_status( $status ) {
$product_status = apply_filters(
'wcv_product_status',
array(
'publish' => __( 'Online', 'wcvendors-pro' ),
'future' => __( 'Scheduled', 'wcvendors-pro' ),
'draft' => __( 'Draft', 'wcvendors-pro' ),
'pending' => __( 'Pending Approval', 'wcvendors-pro' ),
'private' => __( 'Admin Only', 'wcvendors-pro' ),
'trash' => __( 'Trash', 'wcvendors-pro' ),
)
);
return $product_status[ $status ];
} // product_status()
I have created an additional custom post status 'Refunded' and I would like to add this custom status to the existing statuses.
So I'm trying to tap into the filter 'wcv_product_status' to create a function that adds my new product status.
My coding knowledge is really poor and I'm just struggling to finish my snippet.
This is what I currently have:
add_filter( 'wcv_product_status', 'refunded_product_status' );
function refunded_product_status( $status ) {
'refunded' => __( 'Refunded', 'wcvendors-pro' );
return $status;
}
I guess I should be using the 'product_status' somewhere in my snippet, but how would I compile the whole thing together?
Any hint is really appreciated.
You've to change the existing array which you received as a parameter and return it.
add_filter( 'wcv_product_status', 'refunded_product_status', 20, 1 );
function refunded_product_status( $status ) {
$status['refunded'] = __( 'Refunded', 'wcvendors-pro' );
return $status;
}
I'm new and I'm trying to code a crypto payment gateway for WooCommerce by integrating with Metamask. When I press "Place Order" it could trigger Metamask Chrome Ext to pop but then I get "Error processing checkout. Please try again" on the checkout page. WC status log shows nothing. Debug logs nothing too as well as no error in browser console.
Anyway, how do I add a "loading" spinner on checkout page while the payment is processing?
add_filter( 'woocommerce_payment_gateways', 'add_custom_gateway_class' );
function add_custom_gateway_class( $gateways ) {
$gateways[] = 'WC_Crypto_Gateway';
return $gateways;
}
add_action( 'plugins_loaded', 'initialize_gateway_class' );
function initialize_gateway_class() {
class WC_Crypto_Gateway extends WC_Payment_Gateway {
public function __construct() {
$this->id = 'crypto'; // payment gateway ID
$this->icon = ''; // payment gateway icon
$this->has_fields = true; // for custom credit card form
$this->title = __( 'Crypto Payment Gateway', 'text-domain' ); // vertical tab title
$this->method_title = __( 'Crypto Payment Gateway', 'text-domain' ); // payment method name
$this->method_description = __( 'To allow users to pay using cryptocurrencies such as ETH', 'text-domain' ); // payment method description
// load backend options fields
$this->init_form_fields();
// load the settings.
$this->init_settings();
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->enabled = $this->get_option( 'enabled' );
// Action hook to saves the settings
if(is_admin()) {
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
}
// Action hook to load custom JavaScript
add_action( 'wp_enqueue_scripts', array( $this, 'payment_gateway_scripts' ) );
}
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'text-domain' ),
'label' => __( 'Enable Crypto Payment Gateway', 'text-domain' ),
'type' => 'checkbox',
'description' => __( 'This enable the gateway which allow to accept payment via cryptocurrency.', 'text-domain' ),
'default' => 'no',
'desc_tip' => true
),
'description' => array(
'title' => __( 'Description', 'text-domain' ),
'type' => 'textarea',
'description' => __( 'This controls the description which the user sees during checkout.', 'text-domain' ),
'default' => __( 'Pay with your cryptos such as ETH, BTC.', 'text-domain' ),
)
);
}
public function payment_fields() {
}
public function payment_gateway_scripts() {
global $woocommerce;
// process a token only on cart/checkout pages
if ( ! is_cart() && ! is_checkout() ) {
return;
}
// stop enqueue JS if payment gateway is disabled
if ( 'no' === $this->enabled ) {
return;
}
// stop enqueue JS if site without SSL
if ( ! is_ssl() ) {
return;
}
?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/5.5.3/ethers.umd.min.js"></script>
<?php
wp_register_script( 'woocommerce_pay_crypto', plugins_url( 'web3-connector.js', __FILE__ ) );
wp_enqueue_script( 'woocommerce_pay_crypto' );
}
public function process_payment( $order_id ) {
global $woocommerce;
// get order detailes
$order = wc_get_order( $order_id );
}
}
}
In my js, I basically call the below and disable the order button.
$("form.woocommerce-checkout").on("submit", async function (e) {
e.preventDefault();
//Get the payment total
const tokenAmount = document.getElementById("total-amount");
$("#place_order").html(
'<span class="woocommerce-checkout.processing blockUI.blockOverlay"></span>'
);
$("#place_order").attr("disabled", true);
I'm developing a plugin to integrate my WooCommerce store with a third-party right now, and as part of that integration I need to send the customer a new email with some license keys in it. The email sending functionality is fine, the class and its template are working as intended, but the email's sending twice, and I can't figure out why.
I've combed over the new email class and compared it with vanilla WooCommerce email classes, and can't tell where I'm going wrong. I've also tried using an if (did_action( 'woocommerce_order_status_completed_notification' ) === 1) {} check to limit the trigger function to one email, and even still it's sending two.
The code for my email class is here, which is where I'm assuming the problem to be as it doesn't interface with anything other than the default WooCommerce hooks that are working as expected with the vanilla emails. I've tested it with a number of different hooks (both vanilla WooCommerce ones and those I'm calling from my plugin's code), and I'm getting this same double email regardless. If anyone can see where I'm going wrong it'd be tremendously helpful!
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if ( ! class_exists( 'Foundry_Code_Email', false ) ) :
class Foundry_Code_Email extends WC_Email {
/**
* Set email defaults
*/
public function __construct() {
$this->id = 'foundry_code_email'; // Unique ID for custom email
$this->customer_email = true; // Is a customer email
$this->title = __( 'Foundry Premium Content Email', 'woocommerce' ); // Title field in WooCommerce Email settings
$this->description = __( 'Foundry email is sent when customer purchases Foundry Premium Content', 'woocommerce' ); // Description field in WooCommerce email settings
$this->template_base = WP_PLUGIN_DIR . '/foundry-premium-content/templates/';
$this->template_html = 'emails/foundry-code-email.php';
$this->template_plain = 'emails/plain/foundry-code-email.php';
// $this->template_html = 'emails/customer-refunded-order.php';
$this->placeholders = array(
// '{site_title}' => $this->get_blogname(),
'{order_date}' => '',
'{order_number}' => '',
);
// Trigger email when woocommerce_order_status_completed_notification is called when payment is complete - double email debug
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor to load any other defaults not explicitly defined here.
parent::__construct();
}
/**
* Prepares email content and triggers the email
*
* #param int $order_id
*/
public function trigger( $order_id, $order = false ) {
$this->setup_locale();
if ( $order_id && ! is_a( $order, 'WC_Order') ) {
$order = wc_get_order( $order_id );
}
if ( is_a( $order, 'WC_Order' ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->placeholders['{order_date}'] = wc_format_datetime( $this->object->get_date_created() );
$this->placeholders['{order_number}'] = $this->object->get_order_number();
// Maybe include an additional check to make sure that stuff happened
}
if ( $this->is_enabled() && $this->get_recipient() ) {
// All well, send the email
$this->send ( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
$this->restore_locale();
// Add order note about the same
$this->object->add_order_note( sprintf(__('%s email sent to the customer.', 'woocommerce'), $this->get_title() ) );
// Set order meta to indicate that the welcome email was sent
update_post_meta( $order_id, 'foundry_code_email_sent', 1);
}
/**
* Get email subject.
*
* #since 3.1.0
* #return string
*/
public function get_default_subject() {
return __( '{site_title}: Foundry VTT Premium Content Codes', 'woocommerce' );
}
/**
* Get email heading
*
* #since 3.1.0
* #return string
*/
public function get_default_heading() {
return __('Your Foundry Premium Content Codes', 'woocommerce' );
}
/**
* get_content_html function
*
* #return string
*/
public function get_content_html() {
return wc_get_template_html(
$this->template_html,
array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'additional_content' => $this->get_additional_content(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
), '', $this->template_base
);
}
public function get_content_plain() {
return wc_get_template_html(
$this->template_plain,
array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'additional_content' => $this->get_additional_content(),
'sent_to_admin' => false,
'plain_text' => true,
'email' => $this,
), '', $this->template_base
);
}
public function get_default_additional_content() {
return __( 'Thanks for shopping with us.', 'woocommerce' );
}
/*
* Initialise settings form fields
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => 'Enable this email notification',
'default' => 'yes'
),
'subject' => array(
'title' => __( 'Subject', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->get_subject() ),
'placeholder' => $this->get_default_subject(),
'default' => ''
),
'heading' => array(
'title' => __( 'Email Heading', 'woocommerce' ),
'type' => 'text',
'desc_tip' => true,
'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->get_heading() ),
'placeholder' => $this->get_default_heading(),
'default' => ''
),
'email_type' => array(
'title' => __( 'Email type', 'woocommerce'),
'type' => 'select',
'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
'default' => 'html',
'class' => 'email_type wc-enhanced-select',
'options' => $this->get_email_type_options(),
'desc_tip' => true,
)
);
}
}
endif;
return new Foundry_Code_Email();
?>
I found the root issue with this was that I was returning the email class twice: once in the class file itself and once in my overall functions file.
This was my old code in that functions file:
function fpc_custom_woocommerce_emails( $email_classes ) {
// Custom email for Foundry Premium Content
$plugin_dir = dirname(__DIR__);
include_once( $plugin_dir . '/Includes/class-foundry-code-email.php' );
$email_classes['Foundry_Code_Email'] = new Foundry_Code_Email(); // Add to the list of email classes that WooCommerce loads.
return $email_classes;
}
And this is the revised code in that file now:
function fpc_custom_woocommerce_emails( $email_classes ) {
// Custom email for Foundry Premium Content
$plugin_dir = dirname(__DIR__);
$email_classes['Foundry_Code_Email'] = include_once( $plugin_dir . '/Includes/class-foundry-code-email.php' );
return $email_classes;
}
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>';
}
I added a custom status wc-order-confirmed:
// Register new status
function register_order_confirmed_order_status() {
register_post_status( 'wc-order-confirmed', array(
'label' => 'Potvrzení objednávky',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Potvrzení objednávky <span class="count">(%s)</span>', 'Potvrzení objednávky <span class="count">(%s)</span>' )
) );
}
add_action( 'init', 'register_order_confirmed_order_status' );
// Add to list of WC Order statuses
function add_order_confirmed_to_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-order-confirmed'] = 'Potvrzení objednávky';
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'add_order_confirmed_to_order_statuses' );
I added a custom email wc_confirmed_order:
/**
* A custom confirmed Order WooCommerce Email class
*
* #since 0.1
* #extends \WC_Email
*/
class WC_Confirmed_Order_Email extends WC_Email {
/**
* Set email defaults
*
* #since 0.1
*/
public function __construct() {
// set ID, this simply needs to be a unique name
$this->id = 'wc_confirmed_order';
// this is the title in WooCommerce Email settings
$this->title = 'Potvrzení objednávky';
// this is the description in WooCommerce email settings
$this->description = 'Confirmed Order Notification';
// these are the default heading and subject lines that can be overridden using the settings
$this->heading = 'Potvrzení objednávky';
$this->subject = 'Potvrzení objednávky';
// these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
$this->template_html = 'emails/customer-confirmed-order.php';
$this->template_plain = 'emails/plain/admin-new-order.php';
// Trigger on confirmed orders
add_action( 'woocommerce_order_status_pending_to_order_confirmed', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_processing_to_order_confirmed', array( $this, 'trigger' ) );
// Call parent constructor to load any other defaults not explicity defined here
parent::__construct();
// this sets the recipient to the settings defined below in init_form_fields()
$this->recipient = $this->get_option( 'recipient' );
// if none was entered, just use the WP admin email as a fallback
if ( ! $this->recipient )
$this->recipient = get_option( 'admin_email' );
}
/**
* Determine if the email should actually be sent and setup email merge variables
*
* #since 0.1
* #param int $order_id
*/
public function trigger( $order_id ) {
// bail if no order ID is present
if ( ! $order_id )
return;
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->billing_email;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( $this->object->order_date ) );
$this->replace['order-number'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() )
return;
// woohoo, send the email!
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
/**
* get_content_html function.
*
* #since 0.1
* #return string
*/
public function get_content_html() {
ob_start();
wc_get_template( $this->template_html, array(
'order' => $this->object,
'email_heading' => $this->get_heading()
) );
return ob_get_clean();
}
/**
* get_content_plain function.
*
* #since 0.1
* #return string
*/
public function get_content_plain() {
ob_start();
wc_get_template( $this->template_plain, array(
'order' => $this->object,
'email_heading' => $this->get_heading()
) );
return ob_get_clean();
}
/**
* Initialize Settings Form Fields
*
* #since 2.0
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'type' => 'checkbox',
'label' => 'Enable this email notification',
'default' => 'yes'
),
'recipient' => array(
'title' => 'Recipient(s)',
'type' => 'text',
'description' => sprintf( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', esc_attr( get_option( 'admin_email' ) ) ),
'placeholder' => '',
'default' => ''
),
'subject' => array(
'title' => 'Subject',
'type' => 'text',
'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->subject ),
'placeholder' => '',
'default' => ''
),
'heading' => array(
'title' => 'Email Heading',
'type' => 'text',
'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->heading ),
'placeholder' => '',
'default' => ''
),
'email_type' => array(
'title' => 'Email type',
'type' => 'select',
'description' => 'Choose which format of email to send.',
'default' => 'html',
'class' => 'email_type',
'options' => array(
'plain' => __( 'Plain text', 'woocommerce' ),
'html' => __( 'HTML', 'woocommerce' ),
'multipart' => __( 'Multipart', 'woocommerce' ),
)
)
);
}
} // end \WC_confirmed_Order_Email class
I can see the email in the email settings, and the status in the order statuses dropdown. Now, I need to send my new email whenever the order status is changed to wc-order-confirmed. The transition hook seems to never be firing.
I also tried:
/**
* Register the "woocommerce_order_status_pending_to_quote" hook which is necessary to
* allow automatic email notifications when the order is changed to refunded.
*
* #modified from http://stackoverflow.com/a/26413223/2078474 to remove anonymous function
*/
add_action( 'woocommerce_init', 'so_25353766_register_email' );
function so_25353766_register_email(){
add_action( 'woocommerce_order_status_pending_to_order_confirmed', array( WC(), 'send_transactional_email' ), 10, 10 );
add_action( 'woocommerce_order_status_processing_to_order_confirmed', array( WC(), 'send_transactional_email' ), 10, 10 );
}
Which also doesn't seem to work at all... Any ideas, please?
The hook you need is:
woocommerce_order_status_changed
add_action("woocommerce_order_status_changed", "my_awesome_publication_notification");
function my_awesome_publication_notification($order_id, $checkout=null) {
global $woocommerce;
$order = new WC_Order( $order_id );
if($order->status === 'completed' ) {
// Create a mailer
$mailer = $woocommerce->mailer();
$message_body = __( 'Hello world!!!' );
$message = $mailer->wrap_message(
// Message head and message body.
sprintf( __( 'Order %s received' ), $order->get_order_number() ), $message_body );
// Cliente email, email subject and message.
$mailer->send( $order->billing_email, sprintf( __( 'Order %s received' ), $order->get_order_number() ), $message );
}
}
}
As Xcid's answer indicates, you need to register the email.
In WC 2.2+ I believe you can do this via the following:
add_action( 'woocommerce_order_status_wc-order-confirmed', array( WC(), 'send_transactional_email' ), 10, 10 );
I'd added a filter to WooCommerce 2.3, so when that comes out custom emails will be able to be added to the list of email actions that WooCommerce registers:
// As of WooCommerce 2.3
function so_27112461_woocommerce_email_actions( $actions ){
$actions[] = 'woocommerce_order_status_wc-order-confirmed';
return $actions;
}
add_filter( 'woocommerce_email_actions', 'so_27112461_woocommerce_email_actions' );
As you can see here :
https://github.com/woothemes/woocommerce/blob/f8a161c40673cb019eb96b04c04a774ca040a15a/includes/abstracts/abstract-wc-order.php#L2097
you can use this hook :
do_action( 'woocommerce_order_status_' . $new_status, $this->id );
with you custom status should give :
add_action( 'woocommerce_order_status_wc-order-confirmed' , array( $this, 'trigger' ) );
I imagine that you also add you custom email to the mailer, if not :
just add :
add_filter( 'woocommerce_email_classes', array($this,'edit_woocommerce_email_classes' ));
function edit_woocommerce_email_classes( $email_classes ) {
require_once( 'your-email-class.php' );
$email_classes[ 'WC_Confirmed_Order_Email' ] = new WC_Confirmed_Order_Email();
return $email_classes;
}
Edit :
You need to instanciate woocommerce emails before so you can add
add_action( 'init' , 'initiate_woocommerce_email' );
function initiate_woocommerce_email(){
// Just when you update the order_status on backoffice
if( isset($_POST['order_status']) ) {
WC()->mailer();
}
}
You can try to watch when the order status changed so put this into functions.php:
function confirmed_notifications($order_id, $checkout=null) {
global $woocommerce;
$order = new WC_Order( $order_id );
if( $order->status === 'order-confirmed' ) {
// Trigger transactional email to client
$email = $mailer->emails['WC_Confirmed_Order_Email'];
$email->trigger( $order_id );
}
}
add_action("woocommerce_order_status_changed", "confirmed_notifications");
This function will trigger your email and send it.