I have created a custom plugin to send an email to vendor when "new order received". Here I have used "YITH WooCommerce Multi Vendor / Marketplace" plugin to manage the vendors.
function send_vendor_notification( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
}
$vendor_email = "dilshanudawatta15#gmail.com";
$subject = 'New Order Received';
$message = 'You have received a new order (#' . $order_id . '). Product
Name : (#' . $product_name . ') Product ID : (#'. $product_id .').';
wp_mail( $vendor_email, $subject, $message );
}
add_action( 'woocommerce_thankyou', 'send_vendor_notification' );
This is my function to send an email to vendor. Here I have hardcoded the $vendor_email. This function is working. But I want to find a way to access $vendor_email using $order_id. Woocommerce REST API has not a endpoint to directly access vendor details from latest order.
Can I use "yith_get_vendor" for this? and Is there any easy way to access the vendor email using order id?
If you have the $order_id, you can get access to the vendor's email like this:
$order = wc_get_order( $order_id );
$vendor_id = yith_get_vendor( $order_id, 'vendor' )->id;
$vendor = get_wcmp_vendor( $vendor_id );
$vendor_email = $vendor->user_data->user_email;
echo $vendor_email;
First, you fetch the $order object and then the $vendor_id. Then you can use that id to get the $vendor object and it's email.
Related
I'm trying to learn WooCommerce and WordPress plugins so I'm tweaking around. I'm trying to create a plugin that redirects customer to a custom page after checkout. The custom page/url can be defined when I create the product. Here is my code:
<?php
/*
Plugin Name: Custom Redirect After Sale
Description: Redirects customers to a custom page after a successful sale.
*/
// Register a new meta field for products
add_action( 'add_meta_boxes', 'custom_redirect_meta_box' );
function custom_redirect_meta_box() {
add_meta_box( 'custom_redirect_meta_box', 'Custom Redirect URL', 'custom_redirect_meta_box_callback', 'product', 'side' );
}
function custom_redirect_meta_box_callback( $post ) {
$value = get_post_meta( $post->ID, '_custom_redirect_url', true );
echo '<label for="custom_redirect_url">Custom Redirect URL:</label>';
echo '<input type="text" id="custom_redirect_url" name="custom_redirect_url" value="' . esc_attr( $value ) . '" style="width:100%">';
}
// Save the meta field value when the product is saved
add_action( 'save_post_product', 'save_custom_redirect_meta_box_data' );
function save_custom_redirect_meta_box_data( $post_id ) {
if ( isset( $_POST['custom_redirect_url'] ) ) {
update_post_meta( $post_id, '_custom_redirect_url', sanitize_text_field( $_POST['custom_redirect_url'] ) );
}
}
// Redirect to the custom page after a successful sale
add_action( 'woocommerce_payment_complete', 'custom_redirect_after_sale' );
function custom_redirect_after_sale( $order_id ) {
$order = wc_get_order( $order_id );
//$order->update_status( 'completed' );
$items = $order->get_items();
// Get the first product in the order
$product = reset($items);
// Get the custom redirect URL for the product
//$redirect_url = get_post_meta( $product->get_product_id(), '_custom_redirect_url', true );
$redirect_url = get_post_meta( $product->get_id(), '_custom_redirect_url', true );
//echo "Meta retrieved: " . $redirect_url;
//error_log("callback fired");
//echo "Payment complete ho ho ho";
if( $redirect_url ) {
wp_redirect( $redirect_url );
exit;
}
}
It seems the woocommerce_payment_complete hook is not firing. I tried to echo out the redirect url and text but it doesn't seem to work.
I'm on localhost and I'm using the cash on delivery payment method.
Basing this answer on the great https://rudrastyh.com/ - specifically this tutorial https://rudrastyh.com/woocommerce/thank-you-page.html#redirects this is the code that should work for what you are trying to do.
First, you hook into the template_redirect action to determine the URL where the customer needs to go
Getting the Order ID, you can get the products purchased for that order
Once you have the purchased products, you can get their ID and meta data, the redirect URL you saved for each. Note that while you use WP functions for handling meta, when working with WooCommerce it is best practice to use its CRUD methods. In case in the future they port products to custom tables, your code will continue working.
Implement the redirect with the WP function wp_safe_redirect
Note that what you are trying to achieve will have problems if customers purchase orders with more than 1 product, and you have more than 1 redirect URL. In this implementation, the first product in the order that has a saved redirect URL will override all others
add_action( 'template_redirect', 'purchased_product_redirect');
function purchased_product_redirect(){
if( !function_exists( 'is_wc_endpoint_url' )){
return;
}
// do nothing if we are not on the order received page
if( ! is_wc_endpoint_url( 'order-received' ) || empty( $_GET[ 'key' ] ) ) {
return;
}
// Get the order ID
$order_id = wc_get_order_id_by_order_key( $_GET[ 'key' ] );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get and Loop Over Order Items
foreach ( $order->get_items() as $item_id => $item ) {
$product_id = $item->get_product_id();
$product = wc_get_product($product_id);
if(!$product){
continue;
}
//Get the first product's redirect URL
$product_redirect_url = $product->get_meta('_custom_redirect_url');
if(!$product_redirect_url){
continue;
}
wp_safe_redirect( $product_redirect_url );
exit; // always exit after using wp_safe_redirect
}
}
I have to collect order details and checkout details on my email account on clicking the place an order button in woocommerce and redirect them to home page without paying any order fee. I'm using the elementor with WC.
// Getting an instance of the order object
$order = new WC_Order( $order_id );
$items = $order->get_items();
//Loop through them, you can get all the relevant data:
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
}
`
You can set a default payment gateway in woocommerce without payment(ex:- COD).
you can hook into thank-you page using hook woocommerce_thankyou. then get the order object and relevent inforamtion and send this information using wp_mail() to your email then redirect the user to homepage.
for order information check out this blog.
https://www.businessbloomer.com/woocommerce-easily-get-order-info-total-items-etc-from-order-object/
Use below code and if you need a customized email template.
UPDATE 1.
add_action('woocommerce_thankyou', 'zillion_order_mail_and_redirect', 10, 1);
function zillion_order_mail_and_redirect($order_id)
{
$order = wc_get_order($order_id);
$url = home_url();
$to = 'sendto#example.com';
$subject = 'Order Info';
$body = '';
$headers = array('Content-Type: text/html; charset=UTF-8');
$body .= $order->get_formatted_order_total();
wp_mail($to, $subject, $body, $headers);
wp_safe_redirect($url);
exit;
}
wp_mail() reference: https://developer.wordpress.org/reference/functions/wp_mail/
UPDATE 2:-
You can add your email using woocommerce_email_headers hook to get a copy of the email is being sent to the customer.
add_action('woocommerce_thankyou', 'zillion_order_mail_and_redirect', 10, 1);
function zillion_order_mail_and_redirect($order_id)
{
$url = home_url();
wp_safe_redirect($url);
exit;
}
function zillion_hook_headers( $headers, $id, $order ) {
// The order ID | Compatibility with WC version +3
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
$your_email = '<example#gmail.com>';
$headers .= "To: Order Num $order_id $your_email";
return $headers;
}
add_filter( 'woocommerce_email_headers', 'zillion_hook_headers', 10, 3);
How to send order notification to a business partner when a specific coupon is used?
I found a solution for the instance when the coupon is applied here :
Send an email notification when a specific coupon code is applied in WooCommerce
However, I need to find a solution for when after order is submitted, because the order is not always submitted after coupon is applied.
Each coupon will have its own email address.
First we add a setting field to admin Coupon pages, to set an email recipient for for a coupon:
// Add a custom field to Admin coupon settings pages
add_action( 'woocommerce_coupon_options', 'add_coupon_text_field', 10 );
function add_coupon_text_field() {
woocommerce_wp_text_input( array(
'id' => 'email_recipient',
'label' => __( 'Email recipient', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Send an email notification to a defined recipient' ),
'desc_tip' => true, // Or false
) );
}
// Save the custom field value from Admin coupon settings pages
add_action( 'woocommerce_coupon_options_save', 'save_coupon_text_field', 10, 2 );
function save_coupon_text_field( $post_id, $coupon ) {
if( isset( $_POST['email_recipient'] ) ) {
$coupon->update_meta_data( 'email_recipient', sanitize_text_field( $_POST['email_recipient'] ) );
$coupon->save();
}
}
Then email is sent for each applied coupon to a submitted order, if the email recipient has been set for the applied coupon.
Caution! choose only one of the following functions:
For woocommerce versions Up to 4.3 (new hook)
// For Woocommerce version 4.3+
add_action( 'woocommerce_checkout_order_created', 'custom_email_for_orders_with_applied_coupon' );
function custom_email_for_orders_with_applied_coupon( $order ){
$used_coupons = $order->get_used_coupons();
if( ! empty($used_coupons) ){
foreach ( $used_coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code ); // WC_Coupon Object
$recipient = $coupon->get_meta('email_recipient'); // get recipient
if( ! empty($recipient) ) {
$subject = sprintf( __('Coupon "%s" has been applied'), $coupon_code );
$content = sprintf( __('The coupon code "%s" has been applied by a customer'), $coupon_code );
wp_mail( $recipient, $subject, $content ); // Send email
}
}
}
}
Or for all WooCommerce versions (since version 3.0)
// For all Woocommerce versions (since 3.0)
add_action( 'woocommerce_checkout_update_order_meta', 'custom_email_for_orders_with_applied_coupon' );
function custom_email_for_orders_with_applied_coupon( $order_id ){
$order = wc_get_order( $order_id );
$used_coupons = $order->get_used_coupons();
if( ! empty($used_coupons) ){
foreach ( $used_coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code ); // WC_Coupon Object
$recipient = $coupon->get_meta('email_recipient'); // get recipient
if( ! empty($recipient) ) {
$subject = sprintf( __('Coupon "%s" has been applied'), $coupon_code );
$content = sprintf( __('The coupon code "%s" has been applied by a customer'), $coupon_code );
wp_mail( $recipient, $subject, $content ); // Send email
}
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I am development a plugin for custom payment method for WOoCommerce, where in "public function result()" function I want to access/get product id which is bought.
Below is my code so far but it is not working;
public function result() {
global $woocommerce,$wp;
$order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-
received'] ) );
$orderr = wc_get_order( $order_id );
$itemss = $orderr->get_items();
foreach($itemss as $itemm){
$product_id = $item->get_product_id();
$authenticationcode = get_post_meta($product_id, 'authenticationcode', true );
$merchantcode = get_post_meta($product_id, 'merchantcode', true );
}}
Any help would be very helpful.
I think Inside your foreach loop using a wrong variable.
wrong variable : $item->get_product_id();
Correct varible itemm->get_product_id();
Caveat: I'm a solo freelance designer not a developer ;-)
I've created a custom field in the Wordpress user meta called membership.
I've tried the following code to save the WooCommerce Product Name to the membership custom field on checkout with help from this answer.
Updated attempt:
function wascc_woocommerce_checkout_update_user_meta_membership ( $customer_id, $posted ) {
if (isset($posted['$orderid'])) {
$order = $posted['$orderid'];
}
$theorder = new WC_Order( $order );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
update_user_meta( $customer_id, 'membership', $product_name);
}
}
add_action( 'woocommerce_checkout_update_user_meta', 'wascc_woocommerce_checkout_update_user_meta_membership', 10, 2 );
It produces no error, but does not save the product name to membership.
Help appreciated.
Last question may be related.
as I've commented out, you should use woocommerce_checkout_update_order_meta.
Something like this:
function wascc_woocommerce_checkout_update_user_meta_membership ( $order_id ) {
$theorder = new WC_Order( $order_id );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
// Gets the customer/user ID associated with the order. Guests are 0.
$customer_id = $theorder->get_user_id();
update_user_meta( $customer_id, 'membership', $product_name );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'wascc_woocommerce_checkout_update_user_meta_membership' );
I have doubts with your foreach loop though... you are looping just to get the last item?