woocommerce check zip code before placing order - wordpress

As local delivery is the only option (due to product delivery restrictions) I do not want a customer to get to the checkout page and have to fill out all their details and only then discover we do not deliver to their postcode.
Therefore, I require the same functionality of the Local Delivery postcode check at the Checkout page, but to be added at an earlier stage in the checkout process, such as on the Cart page? Or any other page, for that matter. Best place can be in product page before add to cart option.
i.e.
Enter your postcode to see if we deliver to your area:
Result - a yes or no message appears with further instructions

You can add a new field to the cart by using the woocommerce_cart_coupon hook and then you can create a handler using the template_redirect hook.
Something like the below which we have used on our sites before:
add_action( 'woocommerce_cart_coupon', array(&$this, 'new_woocommerce_cart_coupon'), 10, 0 );
add_action( 'template_redirect', array(&$this, 'new_post_code_cart_button_handler') );
public function new_woocommerce_cart_coupon() {
?>
<br/><br/><p>Enter your postcode</p><label for="post_code">Post Code</label> <input type="text" name="post_code" class="input-text" id="post_code" value="" /> <input type="submit" class="button" name="apply_post_code" value="Check Post Code" />
<?php
}
public function new_post_code_cart_button_handler() {
if( is_cart() && isset( $_POST['post_code'] ) && $_SERVER['REQUEST_METHOD'] == "POST" && !empty( $_POST['post_code'] ) ) {
//validate post code here
}
}

Sounds like your best option is to put the PostCode field at the top of your Billing Details form.
This way, once the PostCode is filled up, the shipping methods will adjust accordingly. As soon as the user goes down the form, the Local Shipping method will no longer be available if their postcode don't allow it.
This solution will only work if you place all the postcodes that you actually deliver to in the PostCode section in the Local Delivery settings in the WooCommerce dashboard:
This will ensure that Local Delivery option will only appear to the postcodes in your list. If the postcode entered is not on the list, the Local Delivery option will disappear on the shipping methods options below the form.
Just add this to your functions.php file:
//Rearrange the Fields in the Checkout Billing Details Form
add_filter("woocommerce_checkout_fields", "new_order_fields");
function new_order_fields($fields) {
$order_list = array(
"billing_postcode",
"billing_first_name",
"billing_last_name",
"billing_email",
"billing_phone",
"billing_company",
"billing_address_1",
"billing_address_2",
"billing_country"
);
foreach($order_list as $field)
{
$ordered_fields[$field] = $fields["billing"][$field];
}
$fields["billing"] = $ordered_fields;
return $fields;
}
Just rearrange the $order_list array according to your preference.

Related

Change Shipping Address title based on selected shipping method in Woocommerce

I want to change the Shipping Address title based on the selected shipping method. So for example when someone chooses flat_rate:1 (or a different shipping method -> wcsdm:7 in the code below) the Shipping Address title should change to "title X".
I already tried some code but without any luck.
add_action( 'woocommerce_before_checkout_shipping_form', 'change_shipment_title' );
function change_shipment_title($method, $index) {
// Targeting checkout page only:
if( is_cart() ) return; // Exit on cart page
if( 'wcsdm:7' === $method->id ) {
echo __("<span>Title X</span>");
}
}
Hope some of you could help me with this

Woocommerce - Remove fields from woocommerce_form_field including validation

I am trying to customise the Woocommerce myaccount page, in particular the edit address page.
I want to display both the shipping + billing address forms on a single page. Ideally, in a single form with a one save button. I also need to remove a lot of the fields, so that it's a much simpler form of just an address (no name, company, etc).
I have implemented the code found on This Answer. It works nicely in that it shows both forms. However, I cannot remove the fields from the forms. If I try code like this:
add_filter( 'woocommerce_billing_fields' , 'custom_override_billing_fields' );
add_filter( 'woocommerce_shipping_fields' , 'custom_override_shipping_fields' );
function custom_override_billing_fields( $fields ) {
unset($fields['billing_country']);
unset($fields['billing_company']);
unset($fields['billing_first_name']);
unset($fields['billing_last_name']);
unset($fields['billing_phone']);
unset($fields['billing_email']);
return $fields;
}
function custom_override_shipping_fields( $fields ) {
unset($fields['shipping_country']);
unset($fields['shipping_company']);
unset($fields['shipping_first_name']);
unset($fields['shipping_last_name']);
return $fields;
}
It doesn't work, the fields are no longer shown but the form does not save on click... it just redirects to /my-account/edit-address/billing/ - and doesn't save. (the same form shown on this page doesn't save either).
I've also tried:
foreach ( $billing_fields as $key => $field ) :
if($key != 'billing_first_name' && $key != 'billing_last_name') :
woocommerce_form_field( $key, $field, $userMeta[$key][0] );
endif;
endforeach;
This removes the field from displaying, BUT the validation still exists - and any filter code I add to functions using
woocommerce_checkout_fields to remove the validation doesn't seem to affect this form at all.
Is there a way to either:
Remove fields from this form generated by woocommerce_form_field including the validation?
Create a custom form that allows me to set the input fields manually in the code, and update any fields that are there, ignoring the validation from Woocommerce completely?
This should work 100%. You need to state whether the fields you are removing is from billing or shipping and this is done by adding the ['billing'] or ['shipping'], whichever it is.
After this, adding the function directly to woocommerce_checkout_fields will apply both for billing and shipping.
For phone and company fields you can disable it in admin panel itself, do it.
Edit: And yes, all validation that was involved with the fields in the past will be removed. You can then apply any validation you need.
add_filter( 'woocommerce_checkout_fields' , 'brandimagemarketer_remove_billing_fields_checkout' );
function brandimagemarketer_remove_billing_fields_checkout( $fields ) {
unset($fields['billing']['billing_country']);
unset($fields['billing']['billing_first_name']);
unset($fields['billing']['billing_last_name']);
unset($fields['billing']['billing_email']);
unset($fields['shipping']['shipping_country']);
unset($fields['shipping']['shipping_first_name']);
unset($fields['shipping']['shipping_last_name']);
unset($fields['shipping']['shipping_email']);
return $fields;
}

Change checkout form based on shipping option woo-commerce

How do you change the woo-commerce checkout form for different shipping options? If they choose free shipping the checkout page displays shipping form. If they choose e-voucher the check out page displays a simpler form.
You can use the below code snippet to hide whichever fields you chose when the "e-voucher" shipping method is chosen. Simply put the following inside your functions file.
<?php
add_filter('woocommerce_checkout_fields', 'evoucher_remove_fields');
function evoucher_remove_fields($fields) {
$shipping_method ='evoucher:1'; // Change this to the value name of your shipping method
global $woocommerce;
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ($chosen_shipping == $shipping_method) {
unset($fields['billing']['billing_address_1']); // Hides billing address line 1
unset($fields['billing']['billing_address_2']); // Hides billing address line 2
}
return $fields;
}
?>
Source
There is a good plugin for such purposes. Its free version includes conditional logic, e.g. change the form with the base on shipping option.

handling response and placing order in woocommerce after redirecting back from payment website

I am developing a payment gateway plugin (For Cybersource Payment) for WooCommerce. I developed it to almost at the end, but one thing is intercepting me to finish and that is the part after redirecting from payment gateway website after successful payment back to my wordpress page (Purchase Confirmation Page - New Wordpress Page created using template in wp-content/themes/my-theme/order-confirm-template.php). But i dont know how to handle the response coming back from payment website. I looked for some woocommerce hooks but nothing worked. I found there is a hook woocommerce_thankyou but that is also not working for me.
Can somebody help me out here in these two points below
1) How to handle response and placed the order properly and remove the items from the cart when coming back after successful payment from gateway website.
2) which page should i redirect back from gateway website? back to the same checkout page or some custom page just like i did.
Any Help with code will be very appreciated. Thanks.
I have used the following code in my plugin, I hope this works for you too :)
First add this code,
function receipt_page($order){
echo $this -> ResponceHandler($order);
}
Now the code for ResponceHandler($order) function,
public function ResponceHandler($order_id){
if(!isset($_POST['ResponseCode'])){
global $woocommerce;
echo '<p>'.__('Thank you for your order, please click the button below to pay with XYZ', 'woocommerce').'</p>';
$order = new WC_Order($order_id);
$order_id = $order_id.'_'.date("ymds");
$post_data = get_post_meta($order_id,'_post_data',true);
update_post_meta($order_id,'_post_data',array());
###Your Form Code HERE###
echo '<form><input value="Proceed To Payment" type="submit" /> </form>';
}
###Haandle the response###
if(isset($_POST['ResponseCode']))
{
if($_POST['ResponseCode']==0){
global $woocommerce;
session_start();
$_SESSION['post']=$_POST;
$order = new WC_Order($order_id);
$order_id = $order_id.'_'.date("ymds");
$post_data = get_post_meta($order_id,'_post_data',true);
update_post_meta($order_id,'_post_data',array());
if($order->status != 'processing'){
$order ->status ='Processing';
$order->payment_complete();
$order -> add_order_note('XYZ Payment Gateway <br>Response message :'.$_POST['ResponseMessage'].'<br>Payment ID :'.$_POST['PaymentID'].'<br>Merchant Reference Number :'.$_POST['MerchantRefNo'].'<br>Transaction ID :'.$_POST['TransactionID'].'');
add_post_meta( $order->id, '_paymentid', sanitize_text_field( $_POST['PaymentID'] ) );
add_post_meta( $order->id, '_trno', sanitize_text_field( $_POST['TransactionID'] ) );
$woocommerce -> cart -> empty_cart();
wp_redirect( $order->get_checkout_order_received_url());
}
}
else {
if($order->status != 'failed'){
$order ->status ='failed';
echo "Payment failed!<br><br><br>Possible Error : ".$_POST['ResponseMessage']."<br>PaymentID: ".$_POST['PaymentID']."<br><br><br>We request you to save these details for further reference. <br>You can always pay for this order by clicking on your name in the top right corner and visiting your orders section."; }
}
}
}

Add custom product field on quick edit option on the product listing of a woocommerce site

How can I add custom product field/s on quick edit screen on the product listing of a woocommerce store?
I am not really sure if this is the best way to do it, but it works great for me
Basically my general goal is to add custom fields for a product, I managed to do it (Adding custom fields to the single product pages) with the help of these useful tuts.
http://www.remicorson.com/mastering-woocommerce-products-custom-fields/
http://www.remicorson.com/woocommerce-custom-fields-for-variations/
I recommend checking those links first before proceeding.
Now, what I wanted to do is to add those custom fields to the quick add option on the product listing.
That's where the resource get scarce.
Basically this is how I did it.
Add your custom field (the html forms) to the quick edit options.
I hooked into the 'woocommerce_product_quick_edit_end' action to accomplish this.
This hook is found on woocommerce->includes->admin->views->html-quick-edit-product.php on line 195
Save your custom field.
I hooked into the 'woocommerce_product_quick_edit_save' action to accomplish this.
This hook is found on woocommerce->includes->admin->class-wc-admin-post-types.php inside the 'quick_edit_save' function on line 929
The previous 2 steps does the trick, it does persist the values, however after updating the custom field via the quick edit option, the data is persisted on the backend, but is not populated to the custom field on the UI. That's why we need the 3rd step.
Add the custom field meta data inside the product listing column, then use js to extract the metadata out then populate it to the custom field
I hooked into the 'manage_product_posts_custom_column' action to add a custom HTML tags (div or whatever) to hold my custom field metadata
Then I used javascript to extract the data out from the meta data and populate it into the custom fields
Step 3 is just a copy of how WooCommerce does this process.
For referrence, take a look at function 'render_product_columns' of woocommerce->includes->admin->class-wc-admin-post-types.php
Also take a look at quick-edit.js located at woocommerce->assets->js->admin
Example Code:
Note that the code below is used for illustration and guide purposes, my actual code is quite long and complex.
Step 1:
add_action( 'woocommerce_product_quick_edit_end', function(){
/*
Notes:
Take a look at the name of the text field, '_custom_field_demo', that is the name of the custom field, basically its just a post meta
The value of the text field is blank, it is intentional
*/
?>
<div class="custom_field_demo">
<label class="alignleft">
<div class="title"><?php _e('Custom Field Demo', 'woocommerce' ); ?></div>
<input type="text" name="_custom_field_demo" class="text" placeholder="<?php _e( 'Custom Field Demo', 'woocommerce' ); ?>" value="">
</label>
</div>
<?php
} );
Step 2:
add_action('woocommerce_product_quick_edit_save', function($product){
/*
Notes:
$_REQUEST['_custom_field_demo'] -> the custom field we added above
Only save custom fields on quick edit option on appropriate product types (simple, etc..)
Custom fields are just post meta
*/
if ( $product->is_type('simple') || $product->is_type('external') ) {
$post_id = $product->id;
if ( isset( $_REQUEST['_custom_field_demo'] ) ) {
$customFieldDemo = trim(esc_attr( $_REQUEST['_custom_field_demo'] ));
// Do sanitation and Validation here
update_post_meta( $post_id, '_custom_field_demo', wc_clean( $customFieldDemo ) );
}
}
}, 10, 1);
Step 3:
add_action( 'manage_product_posts_custom_column', function($column,$post_id){
/*
Notes:
The 99 is just my OCD in action, I just want to make sure this callback gets executed after WooCommerce's
*/
switch ( $column ) {
case 'name' :
?>
<div class="hidden custom_field_demo_inline" id="custom_field_demo_inline_<?php echo $post_id; ?>">
<div id="_custom_field_demo"><?php echo get_post_meta($post_id,'_custom_field_demo',true); ?></div>
</div>
<?php
break;
default :
break;
}
}, 99, 2);
The JS part
jQuery(function(){
jQuery('#the-list').on('click', '.editinline', function(){
/**
* Extract metadata and put it as the value for the custom field form
*/
inlineEditPost.revert();
var post_id = jQuery(this).closest('tr').attr('id');
post_id = post_id.replace("post-", "");
var $cfd_inline_data = jQuery('#custom_field_demo_inline_' + post_id),
$wc_inline_data = jQuery('#woocommerce_inline_' + post_id );
jQuery('input[name="_custom_field_demo"]', '.inline-edit-row').val($cfd_inline_data.find("#_custom_field_demo").text());
/**
* Only show custom field for appropriate types of products (simple)
*/
var product_type = $wc_inline_data.find('.product_type').text();
if (product_type=='simple' || product_type=='external') {
jQuery('.custom_field_demo', '.inline-edit-row').show();
} else {
jQuery('.custom_field_demo', '.inline-edit-row').hide();
}
});
});
Make sure to enqueue the script
Hope this helps anyone, again, I am not sure if this is the best way to do it, but upon examining WooCommerce source, it seems WooCommerce
doesn't provide a convenient hook to accomplish this task with ease (at least not yet)
If you have a better approach than this please share.

Resources