Last active
April 15, 2019 18:47
-
-
Save zainaali/c355a2b27a191daac72c16afb75b98fe to your computer and use it in GitHub Desktop.
WooCommerce: Allow adding multiple products and set price to the cart via the add-to-cart query string
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
application/x-httpd-php functions.php ( PHP script, ASCII text ) | |
<?php | |
/** | |
* | |
* 1. Bond Only - Expedia, Direct, HomeAway | |
* https://readysethost.co/checkout/?add-to-cart=772:1:2.00&rcode=TST2&fname=Mike&lname=Aubor&email=damiike%40gmail.com | |
* 2. Booking Only - Booking.com, Direct, HomeAway | |
* https://readysethost.co/checkout/?add-to-cart=1334:1:1.00&rcode=TST2&fname=Mike&lname=Aubor&email=damiike%40gmail.com | |
* 3. Booking Deposit Only - Direct, HomeAway | |
* https://readysethost.co/checkout/?add-to-cart=1437:1:1.00&rcode=TST2&fname=Mike&lname=Aubor&email=damiike%40gmail.com | |
* 4. Booking Deposit and Bond | |
* https://readysethost.co/checkout/?add-to-cart=1437:1:1.00,772:1:2.00&rcode=TST2&fname=Mike&lname=Aubor&email=damiike%40gmail.com | |
* 5. Reservation and Bond - Direct, HomeAway | |
* https://readysethost.co/checkout/?add-to-cart=1334:1:1.00,772:1:2.00&rcode=TST2&fname=Mike&lname=Aubor&email=damiike%40gmail.com | |
* | |
* Functions: | |
* A. Multiple Products - DONE | |
* B. Custom Price for multiple products - DONE | |
* C.1. Custom Billing Field - DONE | |
* C.2. Custom Billing Field in Orders - DONE | |
* D. Force 3D secure on optional cards - DONE | |
* E. Order status code - DONE | |
* F. Hidden billing fields - DONE | |
* G. Skip cart - DONE | |
* H. Hide order notes - DONE | |
* J. Custom fields to checkout - DONE | |
* K. Hide checkout add-to-cart message - DONE | |
* L. Thank you redirect | |
* M. 3D secure card check | |
* N. Clear cart parameter | |
* / | |
/** | |
* C.2. Custom Billing Field in Orders | |
*/ | |
add_action( 'woocommerce_admin_order_data_after_billing_address', 'wc_custom_checkout_field_display_admin_order_meta', 10, 1 ); | |
function wc_custom_checkout_field_display_admin_order_meta($order){ | |
echo '<p><strong>'.__('Reservation Code').':</strong> ' . get_post_meta( $order->id, 'billing_reservationcode', true ) . '</p>'; | |
} | |
add_action( 'woocommerce_checkout_update_order_meta', 'wc_custom_checkout_field_update_order_meta' ); | |
function wc_custom_checkout_field_update_order_meta( $order_id ) { | |
if ( ! empty( $_POST['billing_reservationcode'] ) ) { | |
update_post_meta( $order_id, 'billing_reservationcode', sanitize_text_field( $_POST['billing_reservationcode'] ) ); | |
} | |
} | |
/** | |
* D. Force 3D secure on optional cards | |
*/ | |
add_filter( 'wc_stripe_require_3ds', '__return_true' ); | |
/** | |
* F. Hidden billing fields | |
*/ | |
add_filter( 'woocommerce_checkout_fields', 'remove_checkout_fields', 9999 ); | |
function remove_checkout_fields( $woo_checkout_fields_array ) { | |
// unset( $woo_checkout_fields_array['billing']['billing_first_name'] ); | |
// unset( $woo_checkout_fields_array['billing']['billing_last_name'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_phone'] ); | |
// unset( $woo_checkout_fields_array['billing']['billing_email'] ); | |
unset( $woo_checkout_fields_array['order']['order_comments'] ); | |
// and to remove the fields below | |
unset( $woo_checkout_fields_array['billing']['billing_company'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_country'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_address_1'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_address_2'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_city'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_state'] ); | |
unset( $woo_checkout_fields_array['billing']['billing_postcode'] ); | |
return $woo_checkout_fields_array; | |
} | |
/** | |
* G. Skip cart | |
*/ | |
add_filter ('add_to_cart_redirect', 'redirect_to_checkout'); | |
function redirect_to_checkout() { | |
return WC()->cart->get_checkout_url(); | |
} | |
/** | |
* H. Hide order notes | |
*/ | |
add_filter('woocommerce_enable_order_notes_field', '__return_false'); | |
/** | |
* K. Hide checkout add-to-cart message | |
*/ | |
add_filter( 'wc_add_to_cart_message_html', '__return_false' ); | |
/* | |
* A. Multiple products | |
*/ | |
function woocommerce_maybe_add_multiple_products_to_cart( $url = false ) { | |
// if( !empty( $_REQUEST['add-to-cart'] ) && false === strpos( $_REQUEST['add-to-cart'], ',' ) ){ | |
// return WC_Form_Handler::add_to_cart_action( $url ); | |
// } | |
// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma. | |
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' )){ | |
return; | |
} | |
// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products). | |
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 ); | |
$product_ids = explode( ',', $_REQUEST['add-to-cart'] ); //var_dump($product_ids); exit; | |
$count = count( $product_ids ); | |
$number = 0; | |
$skip_url = site_url( '/thank-you/', 'https' ); //Thank you page | |
if ( isset( $_GET['fname'] ) ) { | |
$fname = isset( $_GET['fname'] ) ? esc_attr( $_GET['fname'] ) : ''; | |
} | |
if (isset( $_GET['lname'] )) { | |
$lname = isset( $_GET['lname'] ) ? esc_attr( $_GET['lname'] ) : ''; | |
} | |
if (isset( $_GET['email'] )) { | |
$email = isset( $_GET['email'] ) ? esc_attr( $_GET['email'] ) : ''; | |
} | |
if (isset( $_GET['rcode'] )) { | |
$rcode = isset( $_GET['rcode'] ) ? esc_attr( $_GET['rcode'] ) : ''; | |
} | |
/*if (isset ($_GET['skip'] )) { | |
$skip = isset( $_GET['skip'] ) ? esc_attr( $_GET['skip'] ) : ''; | |
if (!empty($skip)) { | |
wp_redirect($skip_url); | |
} | |
}*/ | |
// Set the session data | |
WC()->session->set( 'custom_data', array( 'fname' => $fname, 'lname' => $lname, 'email' => $email, 'rcode' => $rcode) ); | |
foreach ( $product_ids as $id_and_quantity ) { //var_dump($id_and_quantity); exit; | |
// Check for quantities defined in curie notation (<product_id>:<product_quantity>) | |
// https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/#comment-12236 | |
$id_and_quantity = explode( ':', $id_and_quantity ); | |
$product_id = $id_and_quantity[0]; | |
$product_price = $id_and_quantity[2]; | |
//var_dump(round($product_price)); | |
if(round($product_price) <= 0 ){ | |
continue; | |
} | |
$_REQUEST['quantity'] = ! empty( $id_and_quantity[1] ) ? absint( $id_and_quantity[1] ) : 1; | |
if ( ++$number === $count ) { | |
// Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling. | |
$_REQUEST['add-to-cart'] = $product_id; | |
return WC_Form_Handler::add_to_cart_action( $url ); | |
} | |
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) ); | |
$was_added_to_cart = false; | |
$adding_to_cart = wc_get_product( $product_id ); | |
if ( ! $adding_to_cart ) { | |
continue; | |
} | |
$add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->get_type(), $adding_to_cart ); | |
// Variable product handling | |
if ( 'variable' === $add_to_cart_handler ) { | |
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id ); | |
// Grouped Products | |
} elseif ( 'grouped' === $add_to_cart_handler ) { | |
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id ); | |
// Custom Handler | |
} elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ){ | |
do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url ); | |
// Simple Products | |
} else { | |
woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id ); | |
} | |
} | |
} | |
// Fire before the WC_Form_Handler::add_to_cart_action callback. | |
add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 ); | |
/** | |
* Invoke class private method | |
* | |
* @since 0.1.0 | |
* | |
* @param string $class_name | |
* @param string $methodName | |
* | |
* @return mixed | |
*/ | |
function woo_hack_invoke_private_method( $class_name, $methodName ) { | |
if ( version_compare( phpversion(), '5.3', '<' ) ) { | |
throw new Exception( 'PHP version does not support ReflectionClass::setAccessible()', __LINE__ ); | |
} | |
$args = func_get_args(); | |
unset( $args[0], $args[1] ); | |
$reflection = new ReflectionClass( $class_name ); | |
$method = $reflection->getMethod( $methodName ); | |
$method->setAccessible( true ); | |
$args = array_merge( array( $reflection ), $args ); | |
return call_user_func_array( array( $method, 'invoke' ), $args ); | |
} | |
/** | |
* J. Autofill check-out | |
*/ | |
// Autofill checkout fields from user data saved in Woocommerce session | |
add_filter( 'woocommerce_billing_fields' , 'prefill_billing_fields', 99999 ); | |
function prefill_billing_fields ( $address_fields ) { | |
// Get the session data | |
$data = WC()->session->get('custom_data'); | |
// First Name | |
if( isset($data['fname']) && ! empty($data['fname']) ) | |
$address_fields['billing_first_name']['default'] = $data['fname']; | |
// Last Name | |
if( isset($data['lname']) && ! empty($data['lname']) ) | |
$address_fields['billing_last_name']['default'] = $data['lname']; | |
//var_dump( $data['lname']);exit; | |
if( isset($data['email']) && ! empty($data['email']) ) | |
$address_fields['billing_email']['default'] = $data['email']; | |
// reservationcode | |
if( isset($data['rcode']) && ! empty($data['rcode']) ) | |
$address_fields['billing_reservationcode']['default'] = $data['rcode']; | |
return $address_fields; | |
} | |
/** | |
* C.1. Custom Billing Field | |
*/ | |
add_filter( 'woocommerce_billing_fields' , 'wc_custom_fields' ); | |
function wc_custom_fields( $fields ) { | |
$fields['billing_reservationcode'] = array( | |
'type' => 'text', | |
'required' => true, | |
'class' => array('reservationcode'), | |
'label' => 'Reservation Code', | |
'label_class' => 'reservation-code' | |
); | |
return $fields; | |
} | |
/* | |
* J. Autofill check-out | |
*/ | |
// Get the custom "amount" from URL and save it as custom data to the cart item | |
add_filter( 'woocommerce_add_cart_item_data', 'add_pack_data_to_cart_item_data', 20, 2 ); | |
function add_pack_data_to_cart_item_data( $cart_item_data, $product_id ){ | |
if( ! isset($_GET['add-to-cart']) ) | |
return $cart_item_data; | |
$amount = esc_attr( $_GET['add-to-cart'] ); | |
if( empty($amount) ) | |
return $cart_item_data; | |
// Set the custom amount in cart object | |
$products = explode( ',', $_GET['add-to-cart'] ); | |
$count = count( $products ); | |
foreach ($products as $product) { | |
$id_and_quantity = explode( ':', $product ); | |
if ($product_id == $id_and_quantity[0]) { | |
$cart_item_data['custom_price'] = $id_and_quantity[2]; | |
} | |
} | |
return $cart_item_data; | |
} | |
/* | |
* B. Custom Price for multiple products | |
*/ | |
// Alter conditionally cart item price based on product ID and custom registered "amount" | |
add_action( 'woocommerce_before_calculate_totals', 'change_conditionally_cart_item_price', 30, 1 ); | |
function change_conditionally_cart_item_price( $cart ) { | |
if ( is_admin() && !defined('DOING_AJAX') ) | |
return; | |
// HERE set your targeted product ID | |
foreach ( $cart->get_cart() as $cart_item ) { | |
// Checking for the targeted product ID and the registered "amount" cart item custom data to set the new price | |
//$cart_item['data']->get_id() == $targeted_product_id && | |
if( isset($cart_item['custom_price']) ) | |
$cart_item['data']->set_price($cart_item['custom_price']); | |
} | |
} | |
/* | |
* E. Order status code | |
*/ | |
//Method to set order status failed or completed based on Stripe 3D. | |
add_action( 'wc_gateway_stripe_process_response', 'prefix_wc_gateway_stripe_process_response', 20, 2 ); | |
function prefix_wc_gateway_stripe_process_response( $response, $order ){ | |
if($response->source->type == 'three_d_secure'){ | |
$order->update_status('completed', 'order_note'); | |
}elseif($response->source->type == 'card'){ | |
$order->update_status('failed', 'order_note'); | |
} | |
} | |
/* | |
* L. Thank you redirect | |
*/ | |
add_action( 'woocommerce_thankyou', 'bbloomer_redirectcustom'); | |
function bbloomer_redirectcustom( $order_id ){ | |
$order = new WC_Order( $order_id ); | |
$url = site_url( '/orders/thank-you/', 'https' ); //Thank you page | |
$mem_url = site_url( '/orders/next-step/', 'https' ); // denied page | |
/*if ( $order->status == 'failed' ) { | |
wp_redirect($mem_url); | |
} | |
else{ | |
wp_redirect($url); | |
}*/ | |
if ( $order->get_payment_method() == 'bacs') { | |
wp_redirect($bacs_url); | |
} | |
else { | |
if ( $order->status == 'failed' ) { | |
wp_redirect($mem_url); | |
} | |
else{ | |
wp_redirect($url); | |
} | |
} | |
} | |
/* | |
* M. 3D secure card check | |
*/ | |
add_filter('wc_stripe_generate_payment_request', 'prefix_wc_stripe_generate_payment_request', 20, 3); | |
function prefix_wc_stripe_generate_payment_request($post_data, $order, $prepared_source){ | |
$data = WC()->session->get('custom_data'); | |
$post_data['statement_descriptor'] = 'RSH ' . $data['rcode']; | |
$post_data['description'] = 'RSH ' . $data['rcode']; | |
if($response->source_object->type != 'three_d_secure'){ | |
//$prepared_source->source_object->status = 'canceled'; | |
$post_data['capture'] = 'false'; | |
//WC_Stripe_Logger::log( 'wc_stripe_generate_payment_request canceled: ' . print_r( $prepared_source->source_object->status, true ) ); | |
} | |
//WC_Stripe_Logger::log( 'wc_stripe_generate_payment_request response: ' . print_r( $prepared_source, true ) ); | |
//WC_Stripe_Logger::log( 'post_data response: ' . print_r( $post_data, true ) ); | |
return $post_data; | |
} | |
add_action('init', 'skip_param'); | |
function skip_param(){ | |
if($_GET['skip'] == 'T'){ | |
$skip_url = site_url( '/thank-you/', 'https' ); //Thank you page | |
wp_redirect($skip_url); | |
exit(); | |
} | |
} | |
/* | |
* N. Clear cart parameter | |
*/ | |
/*empty cart if user come to homepage*/ | |
add_action( 'init', 'woocommerce_clear_cart_url' ); | |
function woocommerce_clear_cart_url() { | |
if ( isset( $_GET['clear-cart'] ) ) { | |
global $woocommerce; | |
$woocommerce->cart->empty_cart(); | |
$skip_url = site_url( '/orders/clear/', 'https' ); | |
wp_redirect($skip_url); | |
exit(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment