Gifting for WooCommerce Subscriptions Add User Role - woocommerce

I'm using Gifting for WooCommerce Subscriptions which makes it possible for one person to purchase a subscription product for someone else.
When the subscription is purchased, I add a user role to the user who purchased the product:
add_action( 'woocommerce_order_status_completed', 'add_role_on_purchase' );
function add_role_on_purchase( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
$products_to_check = array( '12345' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Add role
$user->add_role( 'purchaser' );
// Exit the loop
break;
}
}
}
Gifting for WooCommerce Subscriptions creates a user and a user account for the recipient.
I need to add a user role to the recipient as well. Can this be done after the purchaser's subscription is set to active?

Buying a subscription as a gift, a buyer provides a recipient's email address. You can take the provided email and find the recipient using the get_user_by() function. Having a WP_User instance of the recipient, you can repeat the same logic you do for buyers.
A recipient email address provided by a buyer is probably stored somewhere in an order's meta.

Related

How to link WooCommerce guest orders to customer account after registration

Our scenario is:
The guest user enters the site and places one or more orders without the need to register. And after a while, he decides to register on the site.
Now how to link guest orders to customer account after registeration?
I use the following code, but this code only works for users who have already registered but did not log in at the time of purchase. Any advice?
//assign user in guest order
add_action( 'woocommerce_new_order', 'action_woocommerce_new_order', 10, 1 );
function action_woocommerce_new_order( $order_id ) {
$order = new WC_Order($order_id);
$user = $order->get_user();
if( !$user ){
//guest order
$userdata = get_user_by( 'email', $order->get_billing_email() );
if(isset( $userdata->ID )){
//registered
update_post_meta($order_id, '_customer_user', $userdata->ID );
}else{
//Guest
}
}
}
You can use the woocommerce_created_customer action hook and the wc_update_new_customer_past_orders() function
So you get:
function action_woocommerce_created_customer( $customer_id, $new_customer_data, $password_generated ) {
// Link past orders to this newly created customer
wc_update_new_customer_past_orders( $customer_id );
}
add_action( 'woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3 );

woocommerce get 'billing_phone' field on checkout page

add_action('woocommerce_order_status_completed', 'my_order_status_completed_sms', 10, 1);
function my_order_status_completed_sms($order_id){
$order = wc_get_order($order_id);
$user_id = $order->get_customer_id();
if($user_id){
$phone_number = get_user_meta($user_id, 'billing_phone', true);
if($phone_number){
cosmosfarm_members_sms_send($phone_number, '#'.$order_id.' is complete. thank you!');
}
}
}
When someone purchases from a woocommerce, woocommerce send sms by plug-in.
but there's some issues.
If the buyer is a member, sms will be sent out normally, no problem.
However, if the buyer is not a guest, no sms will be sent.
What's the problem?
Your function is dependend upon having user_id and getting the user_meta for that user.
function my_order_status_completed_sms( $order_id ) {
// Get the order object
$order = wc_get_order( $order_id );
// Get the billing phone number from the order
$phone_number = $order->get_billing_phone();
if ( $phone_number ) {
cosmosfarm_members_sms_send( $phone_number, '#' . $order_id . ' is complete. thank you!' );
}
}
Using the order object, the biling phone is there if entered for either customer or guest.

Order status still “Pending Payment” after successful payment (Custom payment gateway)

I was develop a custom payment gateway for woocommerce, everything is good but after payment success the order still "pending payment"
In the __construct() function I check for payment provider respond
<?php
//when payment done and redirected with payment reference code
if(isset($_REQUEST['transaction_id'])){
paytabs_set_cookie('transaction_id', $_REQUEST['transaction_id']);
$order = new WC_Order($order_id);
$this->order = $order;
$this->complete_transaction($order->get_id(), $_REQUEST['transaction_id']);
}
and here is the complete_transaction() function
<?php
/*
When transaction completed it is check the status
is transaction completed or rejected
*/
function complete_transaction($order_id, $transaction_id) {
global $woocommerce;
$order = new WC_Order( $order_id );
$request_string=array(
'secret_key' => $_COOKIE['secret_key'],
'merchant_email' => $_COOKIE['merchant_email'],
'transaction_id' => $transaction_id,
'order_id' => $order_id
);
$gateway_url=$this->liveurl.'apiv2/verify_payment_transaction';
$getdataresponse=$this->sendRequest($gateway_url, $request_string);
$object=json_decode($getdataresponse, true);
if (isset($object->response_code)) {
//if get response successfull
if($object->response_code == '100'){
// thankyou and set error message
$this->msg['class'] = 'woocommerce_message';
$check=$order->payment_complete();
// Reduce stock levels
$order->reduce_order_stock();
// Remove cart
$woocommerce->cart->empty_cart();
wc_add_notice( '' . __( 'Thank you for shopping with us. Your account has been charged and your transaction is successful.
We will be shipping your order to you soon.', 'woocommerce' ), 'success' );
wp_redirect( $this->get_checkout_order_received_url( $order ) );
exit;
}else{
// Change the status to pending / unpaid
$order->update_status('failed', __('Payment Cancelled', 'error'));
// Add error for the customer when we return back to the cart
$message=$object->result;
wc_add_notice( '<strong></strong> ' . __($message, 'error' ), 'error' );
// Redirect back to the last step in the checkout process
wp_redirect( $this->get_cancel_order_url( $order ) );
exit;
}
}
}
But the order status still "pending payment".
now I need to change the order status to "Completed" after check the payment provider respond.
Fixed
The problem because of this line
wp_redirect( $this->get_checkout_order_received_url( $order ) );
it must be $order instead of $this so the line is like this
wp_redirect( $order->get_checkout_order_received_url( $order ) );

Add customer as recipient to woocommerce subscriptions cancelled subscription email (notification)

By default woocommerce subscriptions send the email notification that a subscription has been cancelled only to the admin of the store, NOT to the customer. This is not user friendly. I am trying to add the customer as a recipient to this specific email notification, without success so far.
I have tried writing add a filter with PhP to the action cancelled_subscription_notification . Which i believe handles the email notification for cancelled subscriptions.
add_filter( 'cancelled_subscription_notification',
'wc_cancelled_order_add_customer_email', 10, 2 );
function wc_cancelled_order_add_customer_email( $recipient, $order ){
// Avoiding errors in backend (mandatory when using $order argument)
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;
// Get the customer ID
$user_id = $order->get_user_id();
// Get the user data
$user_data = get_userdata( $user_id );
return $recipient;
}
When using this code (added in functions.php) i get an error 500 when i cancel a subscription (the actual email to admin is also not send!).
Useful maybe: https://github.com/wp-premium/woocommerce-subscriptions/blob/master/includes/emails/class-wcs-email-cancelled-subscription.php (link to cancelled-subscription calls)

Woocommerce Get Vendor Information with Product ID

I am using Woo Commerce with WC Vendor and WC Booking plugin. I want to send booking notification to vendor. Currently it sends notification to Customer and Administrator and when admin changes product status to processing & completed, then it sends notification to vendor. However, I want to send vendor notification along with admin notification.
I tried this hook:
add_action( 'woocommerce_new_booking', 'new_order_email_to_vendor', 10, 4 );
function new_order_email_to_vendor( $order ){
$emails = WC()->mailer()->get_emails();
if ( ! empty( $emails ) ) {
$emails['WC_Product_Vendors_Order_Email_To_Vendor']->trigger( $order );
}
}
But it throws an error:
Fatal error: Call to a member function get_date_created() on boolean in /wp-content/plugins/woocommerce-product-vendors/includes/emails/class-wc-product-vendors-order-email-to-vendor.php on line 56
So, now I am trying to hook vendor email directly along with customer and administrator email in this line:
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ), 'WILL ADD VENDOR EMAIL HERE' );
in file:
wp-content/plugins/woocommerce-bookings/includes/emails/class-wc-email-new-booking.php
At this stage, I have bookable product id available and I am trying to pull vendor information using product id but I don't found any information.
I tried:
get_post()
get_post_meta()
get_post_meta_by_id()
The Question is: How to get vendor information (specifically email) using product id?
I don't have and I have never used WC Vendors plugin as this is a non official commercial plugin (not made by automatic).
To get the vendor ID (after searching a bit) you can get it this way from a product ID:
$vendor_id = get_post_field( 'post_author', $product_id );
Now you can get the vendor email this way:
$vendor_id = get_post_field( 'post_author', $product_id );
$vendor = get_userdata( $vendor_id );
$email = $vendor->user_email;
May be a good turn around:
You can use the dedicated filter hook woocommerce_email_recipient_{$this->id} where $this->id is the ID of the notification type, for new_booking email ID (and also for testing new_order email ID too).
This will allow you to add additional email recipients.
In email notifications hooks, the Order object is nearly always defined. As In an order you can have many items (different products rom different vendors), you will need to get the vendor ID from each.
In the code below I add to the recipients the vendors emails for new_booking and new_order email notifications:
add_filter( 'woocommerce_email_recipient_new_booking', 'additional_customer_email_recipient', 10, 2 );
add_filter( 'woocommerce_email_recipient_new_order', 'additional_customer_email_recipient', 10, 2 ); // Optional (testing)
function additional_customer_email_recipient( $recipient, $order ) {
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;
$additional_recipients = array(); // Initializing…
// Iterating though each order item
foreach( $order->get_items() as $item_id => $line_item ){
// Get the vendor ID
$vendor_id = get_post_field( 'post_author', $line_item->get_product_id());
$vendor = get_userdata( $vendor_id );
$email = $vendor->user_email;
// Avoiding duplicates (if many items with many emails)
// or an existing email in the recipient
if( ! in_array( $email, $additional_recipients ) && strpos( $recipient, $email ) === false )
$additional_recipients[] = $email;
}
// Convert the array in a coma separated string
$additional_recipients = implode( ',', $additional_recipients);
// If an additional recipient exist, we add it
if( count($additional_recipients) > 0 )
$recipient .= ','.$additional_recipients;
return $recipient;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This should work without errors.

Resources