I am creating a custom gateway plugin for woocommerce for which I need the following workflow:
When customers click on the PLACE ORDER button on the checkout page
they need to be directed to the bank's hosted payment page to enter the card details and make the
payment. Once the payment is made, the bank sends the success/fail
response, and then only the order status is updated to
complete/canceled.
Also, the bank needs some information like merchant ID and other fields to process the payment.
I have created the plugin which adds hidden fields in the checkout page with necessary data that needs to be sent to the bank's payment page but I am having difficulties passing the data to the hosted payment page. Below is my full code
<?php
/*
** Check if Woocommerce is active
**
*/
if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) return;
// create custom plugin settings menu
add_action('admin_menu', 'create_custom_menu');
function create_custom_menu() {
//create new top-level menu
add_menu_page('Plugin page Settings', 'Plugin Settings', 'administrator', __FILE__, 'plugin_settings_page' , plugins_url('/images/icon.png', __FILE__) );
//call register settings function
add_action( 'admin_init', 'register_plugin_settings' );
}
function register_plugin_settings() {
//register our settings
register_setting( 'plugin-settings-group', 'shop_id' );
register_setting( 'plugin-settings-group', 'shared_secret' );
register_setting( 'plugin-settings-group', 'currency_code' );
}
function plugin_settings_page() {
?>
<div class="wrap">
<form method="post" action="options.php">
<?php settings_fields( 'plugin-settings-group' ); ?>
<?php do_settings_sections( 'plugin-settings-group' ); ?>
<table class="form-table">
<tr valign="top">
<th scope="row">Shop ID</th>
<td><input type="text" name="shop_id" value="<?php echo esc_attr( get_option('shop_id') ); ?>" /></td>
</tr>
<tr valign="top">
<th scope="row">Shared Secret</th>
<td><input type="text" name="shared_secret" value="<?php echo esc_attr( get_option('shared_secret') ); ?>" /></td>
</tr>
<tr valign="top">
<th scope="row">Currency Code</th>
<td><input type="text" name="currency_code" value="<?php echo esc_attr( get_option('currency_code') ); ?>" disabled/><br></td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php }
add_action( 'woocommerce_after_order_notes', 'add_custom_checkout_hidden_field' );
function add_custom_checkout_hidden_field( $checkout ) {
$shop_id = esc_attr( get_option('shop_id') );
$sharedSecret = esc_attr( get_option('shared_secret') );
$currency = "826";
// Output the hidden field
echo '<input type="hidden" name="shop_id" value="'.$shop_id.'" />
<input type="hidden" name="shop_id" value="'.$sharedSecret.'" />
<input type="hidden" name="shop_id" value="'.$currency.'" />
';
}
add_filter( 'woocommerce_payment_gateways', 'add_custom_gateway_class' );
function add_custom_gateway_class( $gateways ) {
$gateways[] = 'Custom_Gateway';
return $gateways;
}
add_action( 'plugins_loaded', 'plugin_init_gateway_class' );
function plugin_init_gateway_class() {
class Custom_Gateway extends WC_Payment_Gateway {
/**
* Class constructor
*/
public function __construct() {
$this->id = 'custom_gateway_id'; // payment gateway plugin ID
$this->icon = ''; // URL of the icon that will be displayed on checkout page near your gateway name
$this->has_fields = true; // in case you need a custom credit card form
$this->method_title = 'Custom Gateway';
$this->method_description = 'Description of Custom payment gateway'; // will be displayed on the options page
// Method with all the 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' );
$this->shop_id = $this->get_option( 'shop_id' );
$this->test_mode = $this->get_option( 'test_mode' );
// This action hook saves the settings
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
}
public function getDateTime(){
date_default_timezone_set('Europe/London');
$dateTime = date("Y:m:d-H:i:s");
global $dateTime;
return $dateTime;
}
public function createHash($chargetotal, $currency){
$storeId = $this->get_option( 'shop_id' );
$sharedSecret = $this->get_option( 'shared_secret' );
$stringToHash = $storeId.getDateTime().$chargetotal.$currency.$sharedSecret;
$ascii = bin2hex($stringToHash);
return hash("sha256", $ascii);
}
public function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'label' => 'Enable Custom Gateway',
'type' => 'checkbox',
'description' => '',
'default' => 'no'
),
'title' => array(
'title' => 'Title',
'type' => 'text',
'description' => 'This controls the title which the user sees during checkout.',
'default' => 'Debit/Credit Card',
'desc_tip' => true,
),
'description' => array(
'title' => 'Description',
'type' => 'textarea',
'description' => 'This controls the description which the user sees during checkout.',
'default' => 'Pay with your debit/credit card.',
),
'test_mode' => array(
'title' => 'Test Mode',
'type' => 'checkbox',
'description' => 'Check this option to enable the test mode.',
'default' => 'yes',
)
);
}
public function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$environment = $this->get_option( 'test_mode' );
if ($environment === 'yes') {
// TEST MODE
$redirect_url = 'https://mytesturl.com';
} else{
// PRODUCTION MODE
$redirect_url = 'https://myproductionurl.com';
}
return array(
'result' => 'success',
'redirect' => $redirect_url
);
}
}
}
Can someone assist me please, how can I pass the required data to the hosted payment page and update the order status once the response is received from the bank?
Related
I'm trying to add a second product description to my WooCommerce page: https://alvinecph.dk/kategori/to-go/ from the guide from https://www.businessbloomer.com/woocommerce-add-a-second-content-box-product-category-pages/ .
I do however experience an issue, that the second description isn't showing for the hook woocommerce_after_shop_loop. I've tried to change the hook to woocommerce_before_shop_loop_item, and this seems to work, showing the text. So it could seem like woocommerce_after_shop_loop isn't present on the page.
I'm using the Divi theme, and have created a template for the category/archive page with their builder. To this template I've the Woo Product block. So I'm really baffled about this.
Is there something I'm missing. I've also tried to disable all plugins.
BR
Martin
// 1. Display field on "Add new product category" admin page
add_action( 'product_cat_add_form_fields', 'bbloomer_wp_editor_add', 10, 2 );
function bbloomer_wp_editor_add() {
?>
<div class="form-field">
<label for="seconddesc"><?php echo __( 'Second Description', 'woocommerce' ); ?></label>
<?php
$settings = array(
'textarea_name' => 'seconddesc',
'quicktags' => array( 'buttons' => 'em,strong,link' ),
'tinymce' => array(
'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
'theme_advanced_buttons2' => '',
),
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
);
wp_editor( '', 'seconddesc', $settings );
?>
<p class="description"><?php echo __( 'This is the description that goes BELOW products on the category page', 'woocommerce' ); ?></p>
</div>
<?php
}
// ---------------
// 2. Display field on "Edit product category" admin page
add_action( 'product_cat_edit_form_fields', 'bbloomer_wp_editor_edit', 10, 2 );
function bbloomer_wp_editor_edit( $term ) {
$second_desc = htmlspecialchars_decode( get_woocommerce_term_meta( $term->term_id, 'seconddesc', true ) );
?>
<tr class="form-field">
<th scope="row" valign="top"><label for="second-desc"><?php echo __( 'Second Description', 'woocommerce' ); ?></label></th>
<td>
<?php
$settings = array(
'textarea_name' => 'seconddesc',
'quicktags' => array( 'buttons' => 'em,strong,link' ),
'tinymce' => array(
'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
'theme_advanced_buttons2' => '',
),
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
);
wp_editor( $second_desc, 'seconddesc', $settings );
?>
<p class="description"><?php echo __( 'This is the description that goes BELOW products on the category page', 'woocommerce' ); ?></p>
</td>
</tr>
<?php
}
// ---------------
// 3. Save field # admin page
add_action( 'edit_term', 'bbloomer_save_wp_editor', 10, 3 );
add_action( 'created_term', 'bbloomer_save_wp_editor', 10, 3 );
function bbloomer_save_wp_editor( $term_id, $tt_id = '', $taxonomy = '' ) {
if ( isset( $_POST['seconddesc'] ) && 'product_cat' === $taxonomy ) {
update_woocommerce_term_meta( $term_id, 'seconddesc', esc_attr( $_POST['seconddesc'] ) );
}
}
// ---------------
// 4. Display field under products # Product Category pages
add_action( 'woocommerce_after_shop_loop', 'bbloomer_display_wp_editor_content', 5 );
function bbloomer_display_wp_editor_content() {
if ( is_product_taxonomy() ) {
$term = get_queried_object();
if ( $term && ! empty( get_woocommerce_term_meta( $term->term_id, 'seconddesc', true ) ) ) {
echo '<p class="term-description">' . wc_format_content( htmlspecialchars_decode( get_woocommerce_term_meta( $term->term_id, 'seconddesc', true ) ) ) . '</p>';
}
}
}
Good morning,
I wrote/modified the following code to create 2 different new fileds on woocommerce (bithdate, and city of bith).
Everything works like a charm (in admin page, in my account page) but I'd like to show them on checkout page (so at the first time the customer buy something I can collect that info too [required]).
function action_woocommerce_edit_account_form() {
woocommerce_form_field( 'birthday_field', array(
'type' => 'date',
'label' => __( 'Data di nascita', 'woocommerce' ),
'placeholder' => __( 'Data di nascita', 'woocommerce' ),
'required' => true,
), get_user_meta( get_current_user_id(), 'birthday_field', true ));
woocommerce_form_field( 'birthcity_field', array(
'type' => 'text',
'label' => __( 'Città di nascita', 'woocommerce' ),
'placeholder' => __( 'Città di nascita', 'woocommerce' ),
'required' => true,
), get_user_meta( get_current_user_id(), 'birthcity_field', true ));
}
add_action( 'woocommerce_edit_account_form', 'action_woocommerce_edit_account_form' );
// Validate - my account
function action_woocommerce_save_account_details_errors( $args ){
if ( isset($_POST['birthday_field']) && empty($_POST['birthday_field']) ) {
$args->add( 'error', __( 'Prego inserire data di nascita', 'woocommerce' ) );
}
if ( isset($_POST['birthcity_field']) && empty($_POST['birthcity_field']) ) {
$args->add( 'error', __( 'Prego inserire città di nascita', 'woocommerce' ) );
}
}
add_action( 'woocommerce_save_account_details_errors','action_woocommerce_save_account_details_errors', 10, 1 );
// Save - my account
function action_woocommerce_save_account_details( $user_id ) {
if( isset($_POST['birthday_field']) && ! empty($_POST['birthday_field']) ) {
update_user_meta( $user_id, 'birthday_field', sanitize_text_field($_POST['birthday_field']) );
}
if( isset($_POST['birthcity_field']) && ! empty($_POST['birthcity_field']) ) {
update_user_meta( $user_id, 'birthcity_field', sanitize_text_field($_POST['birthcity_field']) );
}
}
add_action( 'woocommerce_save_account_details', 'action_woocommerce_save_account_details', 10, 1 );
// Add field - admin
function add_user_birtday_field( $user ) {
?>
<h3><?php _e('Dati aggiuntivi','woocommerce' ); ?></h3>
<table class="form-table">
<tr>
<th><label for="birthday_field"><?php _e( 'Data di nascita', 'woocommerce' ); ?></label></th>
<td><input type="date" name="birthday_field" value="<?php echo esc_attr( get_the_author_meta( 'birthday_field', $user->ID )); ?>" class="regular-text" /></td>
</tr>
</table>
<br />
<table class="form-table">
<tr>
<th><label for="birthcity_field"><?php _e( 'Città di nascita', 'woocommerce' ); ?></label></th>
<td><input type="text" name="birthcity_field" value="<?php echo esc_attr( get_the_author_meta( 'birthcity_field', $user->ID )); ?>" class="regular-text" /></td>
</tr>
</table>
<br />
<?php
}
add_action( 'show_user_profile', 'add_user_birtday_field', 10, 1 );
add_action( 'edit_user_profile', 'add_user_birtday_field', 10, 1 );
add_action( 'show_user_profile', 'add_user_birthcity_field', 10, 1 );
add_action( 'edit_user_profile', 'add_user_birthcity_field', 10, 1 );
// Save field - admin
function save_user_birtday_field( $user_id ) {
if( ! empty($_POST['birthday_field']) ) {
update_user_meta( $user_id, 'birthday_field', sanitize_text_field( $_POST['birthday_field'] ) );
}
if( ! empty($_POST['birthcity_field']) ) {
update_user_meta( $user_id, 'birthcity_field', sanitize_text_field( $_POST['birthcity_field'] ) );
}
}
add_action( 'personal_options_update', 'save_user_birtday_field', 10, 1 );
add_action( 'edit_user_profile_update', 'save_user_birtday_field', 10, 1 );
add_action( 'personal_options_update', 'save_user_birthcity_field', 10, 1 );
add_action( 'edit_user_profile_update', 'save_user_birthcity_field', 10, 1 );
I'll be very gratefull to everyone who can help me.
Warm regards
Ale
I solved by myself inspired by this article Post on Stackoverflow, BUT as I usual do I'd like to share the solution because could be helpful for someone.
Based on the code posted above You can add the field on the checkout page with the following code:
// Add the field to the checkout
add_action( 'woocommerce_after_checkout_billing_form', 'birth_day_checkout_field' );
function birth_day_checkout_field( $checkout ) {
// if customer is logged in and his birth date is defined
if(!empty(get_user_meta( get_current_user_id(), 'birthday_field', true ))){
$checkout_birht_date = esc_attr(get_user_meta( get_current_user_id(), 'birthday_field', true ));
}
// The customer is not logged in or his birth date is NOT defined
else {
$checkout_birht_date = $checkout->get_value( 'birthday_field' );
}
echo '<p id="custom_birthday_field">';
woocommerce_form_field( 'birthday_field', array(
'type' => 'date',
'class' => array('birth-date form-row-wide'),
'label' => __( 'Data di nascita', 'woocommerce' ),
'placeholder' => __( 'mm/dd/yyyy', 'woocommerce' ),
'required' => true,
), $checkout_birht_date);
echo '</p>';
}
// Process the checkout
add_action('woocommerce_checkout_process','birth_day_checkout_field_process');
function birth_day_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['birthday_field'] )
wc_add_notice( __( 'Inserire la <strong>Data di nascita</strong>', 'woocommerce' ), 'error' )
;
}
// update order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'birth_day_checkout_field_update_order_meta' );
function birth_day_checkout_field_update_order_meta( $order_id ) {
if (!empty( $_POST['birthday_field'])){
update_post_meta( $order_id, 'birthday_field', sanitize_text_field( $_POST['birthday_field'] ) );
// updating user meta (for customer my account edit details page post data)
update_user_meta( get_post_meta( $order_id, '_customer_user', true ), 'birthday_field', sanitize_text_field($_POST['birthday_field']) );
}
}
// update user meta with Birth date (in checkout and my account edit details pages)
add_action ( 'personal_options_update', 'birth_day_save_extra_profile_fields' );
add_action ( 'edit_user_profile_update', 'birth_day_save_extra_profile_fields' );
add_action( 'woocommerce_save_account_details', 'birth_day_save_extra_profile_fields' );
function birth_day_save_extra_profile_fields( $user_id )
{
// for checkout page post data
if ( isset($_POST['birthday_field']) ) {
update_user_meta( $user_id, 'birthday_field', sanitize_text_field($_POST['birthday_field']) );
}
// for customer my account edit details page post data
if ( isset($_POST['birthday_field']) ) {
update_user_meta( $user_id, 'birthday_field', sanitize_text_field($_POST['birthday_field']) );
}
}
In this way this data will be updated everywhere (my account, admin and checkout).
Warm regards
Ale
I'm a newbie to the Wordpress Customization and learning plugin development from a YouTube videos.
Below is the code snippet from my custom plugin that adds the two custom fields meta_title and meta_description in the example create/ edit form.
function ideapro_custom_posttype() {
register_post_type( 'Example',
array(
'labels'=>array(
'name' =>__('Examples'),
'singular_name' => __('Example'),
'add_new' => __('Add New Example'),
'add_new_item' => __('Add New Example'),
'edit_item' => __('Edit Example'),
'search_items' => __('Search Examples')
),
'menu_postion' => 5,
'public' =>true,
'exclude_from_search' => true,
'has_archives'=>false,
'register_meta_box_cb' => 'metaField_metabox',
'supports' => array('title', 'editor', 'thumbnail')
)
);
}
/** Add new custom fields to create post form*/
function metaField_metabox() {
add_meta_box( 'meta_fields', 'Meta Fields', 'display_metaFields', 'example','normal','high' );
}
function display_metaFields(){
global $post;
$meta_title = get_post_meta($post->ID,'meta_title', true);
$meta_description = get_post_meta($post->ID,'meta_description', true);
?>
<label>Meta Title</label>
<input type="text" name="meta_title" placeholder="Meta Title" class="widefat" value="<?php print $meta_title?>">
</br>
</br>
<label>Meta Description</label>
<input type="text" name="meta_description" placeholder="Meta Description"class="widefat" value="<?php print $meta_description?>">
<?php
}
add_action( 'add_meta_box','metaField_metabox' );
/** save custom field data to posts table */
function saveMetaFields($post_id){
$is_autosave = wp_is_post_autosave($post_id );
$is_revision = wp_is_post_revision( $post_id );
if( $is_autosave || $is_revision){
return;
}
$post = get_post($post_id);
if ($post->post_type == "example") {
if (array_key_exists('meta_title', $_POST)) {
update_post_meta( $post_id, 'meta_title',$_POST['meta_title']);
}
if (array_key_exists('meta_description', $_POST)) {
update_post_meta( $post_id, 'meta_description',$_POST['meta_description']);
}
}
}
add_action( 'save_post','saveMetaFields' );
With the above code I'm successful to add custom field data in the posts table.
Now I want to place the meta_title and meta_description of a each post in the header section of a post. Like:
<meta name="title">....</title>
<meta name="description">....</title>
Use wp_head action:
function myAction() {
if(is_single('Example'):
$postID = get_the_ID();
$title = get_post_meta($postID,'meta_title',true);
$desc = get_post_meta($postID,'meta_description',true);
?>
<meta name="title" content="<?php echo $title; ?>" />
<meta name="description" content="<?php echo $desc; ?>"/>
<?php
endif;
}
add_action( 'wp_head', 'myAction' );
i am going to build my own theme
I try to add select to post_type meta box, but every update post my select not on selected option but show the first option (blank value)
here is my code
function mhs_data() {
global $post;
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
$nisn = get_post_meta($post->ID, '_nisn', true);
$rel = get_post_meta($post->ID, '_rel', true);
}
echo '<p>NISN</p>';
echo '<input type="text" name="_nisn" value="' . $nisn . '" class="widefat" />';
echo '<p>Relationship</p>'; ?>
<select name="_rel" id="_rel">
<option value="">Relationship</option>
<option value="Single" <?php selected( $rel, 'Single' ); ?>>Single</option>
<option value="Marry" <?php selected( $rel, 'Marry' ); ?>>Marry</option>
</select>
<?php
}
function mhs_data_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
$events_meta['_nisn'] = $_POST['_nisn'];
$events_meta['_rel'] = $_POST['_rel'];
foreach ($events_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value);
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
}
add_action('save_post', 'mhs_data_meta', 1, 2);
Please help me to correct my code
Using Codestar Framework its very simple tu add metaboxes to your custom post, create configuration page, plugins, taxonomies and use the customizer if you prefer use it instead of a configuration page. see the documentation here for more information.
in your example, to add a select metabox shuld use a code similar to:
load the framework on your functions.php
require_once __DIR__ . '/'.$FRAMEWORK_PATH.'/cs-framework/cs-framework.php';
edit the cs-framekork.php configuration file to active only the features you need:
defined('CS_ACTIVE_FRAMEWORK') or define('CS_ACTIVE_FRAMEWORK', false); // if you need it for plugin or configuration page
defined('CS_ACTIVE_METABOX') or define('CS_ACTIVE_METABOX', true); // if you only need it for metabox
defined('CS_ACTIVE_TAXONOMY') or define('CS_ACTIVE_TAXONOMY', false);
defined('CS_ACTIVE_SHORTCODE') or define('CS_ACTIVE_SHORTCODE', false);
defined('CS_ACTIVE_CUSTOMIZE') or define('CS_ACTIVE_CUSTOMIZE', false);
and then in your function.php or as I prefer on another file included in your function.php register your metabox
function register_this_metabox($options)
{
$options = array(); // this will clean the default cs-framework configuration
$options[] = array(
'id' => 'the_metabox',
'title' => 'Meta Box title',
'post_type' => 'post', // the post type where the metabox appears
'context' => 'side', // metabox position
'priority' => 'high',
'sections' => array( // metabox fields, see the documentation
array(
'name' => 'the_metabox_fields',
'fields' => array(
array(
'id' => 'the_metabox_select_field',
'type' => 'select',
'title' => 'Select Field',
'options' => array(
'opt1' => 'Option 1',
'opt2' => 'Option 2',
'opt3' => 'Option 3',
),
'default_option' => 'Select a option',
),
),
),
),
);
return $options;
}
add_filter('cs_metabox_options', 'register_this_metabox');
And now you only have to get the values in your theme:
$post_metabox = get_post_meta($post->ID, 'the_metabox', true);
$selected_option = $post_metabox['the_metabox_select_field']
I am trying to add a VAT field to the Customer Billing Address, while this works on the Checkout page with the following code:
// Company Name Required
add_filter('woocommerce_checkout_fields','custom_override_checkout_fields');
function custom_override_checkout_fields($fields){
$fields['billing']['billing_company']['required'] = true;
$fields['billing']['billing_vat'] = array(
'label' => __('VAT Number','woocommerce'),
'placeholder' => _x('Enter VAT Number','placeholder','woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
//Display field value on the order edit page
add_action('woocommerce_admin_order_data_after_shipping_address','my_custom_checkout_field_display_admin_order_meta',10,1);
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('VAT Number').':</strong> ' . get_post_meta($order->id,'_billing_vat',true) . '</p>';
}
//Order the fields
add_filter("woocommerce_checkout_fields","order_fields");
function order_fields($fields){
$order = array(
"billing_first_name",
"billing_last_name",
"billing_company",
"billing_vat",
"billing_country",
"billing_city",
"billing_postcode",
"billing_state",
"billing_address_1",
"billing_address_2",
"billing_email",
"billing_phone",
);
foreach($order as $field){$ordered_fields[$field] = $fields["billing"][$field];}
$fields["billing"] = $ordered_fields;
return $fields;
}
I also require it to be set on the Customer Billing Address in the account options. As I require to link this to the registration page as I'd like the users to register with all their credentials including the VAT number they own for a B2B Webstore.
Does anyone know or could anyone point me in the right direction how I would perform this task of not only showing those billing fields of the VAT number on the checkout page but also on the users profile page, as well as how to add all these fields on the registration page?
Thanks in advance for any assistance for this case!
Well, it's quite simple. Your code should be like this:
/* ---------------------- Registration page ----------------------- */
/* Add extra fields in registration form */
add_action( 'woocommerce_register_form_start', 'my_extra_register_fields' );
function my_extra_register_fields() {
?>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<label for="reg_billing_vat"><?php _e( 'Billing VAT', 'woocommerce' ); ?><span class="required">*</span></label>
<input type="text" class="input-text" name="billing_vat" id="reg_billing_vat" value="<?php if ( ! empty( $_POST['billing_vat'] ) ) esc_attr_e( $_POST['billing_vat'] ); ?>">
</p>
<div class="clearfix"></div>
<?php
}
/* registration form fields Validation */
add_action( 'woocommerce_register_post', 'my_validate_extra_register_fields', 10, 3 );
function my_validate_extra_register_fields( $username, $email, $validation_errors ) {
if ( isset( $_POST['billing_vat'] ) && empty( $_POST['billing_vat'] ) ) {
$validation_errors->add( 'billing_vat_error', __( 'VAT number is required!', 'woocommerce' ) );
}
return $validation_errors;
}
/* Below code save extra fields when new user register */
add_action( 'woocommerce_created_customer', 'my_save_extra_register_fields' );
function my_save_extra_register_fields( $customer_id ) {
if ( isset( $_POST['billing_vat'] ) ) {
// VAT field which is used in WooCommerce
update_user_meta( $customer_id, 'billing_vat', sanitize_text_field( $_POST['billing_first_name'] ) );
}
}
/* ---------------------- Account page ----------------------- */
/* Show custom fields on Account details page */
add_action( 'woocommerce_edit_account_form', 'my_woocommerce_edit_account_form' );
function my_woocommerce_edit_account_form() {
$user_id = get_current_user_id();
$user = get_userdata( $user_id );
if ( !$user ) return;
$billing_vat = get_user_meta( $user_id, 'billing_vat', true );
?>
<fieldset>
<legend>Custom information</legend>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<label for="billing_vat">Billing VAT</label>
<input type="text" name="billing_vat" id="billing_vat" value="<?php echo esc_attr( $billing_vat ); ?>" class="input-text" />
</p>
<div class="clearfix"></div>
</fieldset>
<?php
}
/* Below code save extra fields when account details page form submitted */
add_action( 'woocommerce_save_account_details', 'my_woocommerce_save_account_details' );
function my_woocommerce_save_account_details( $user_id ) {
if ( isset( $_POST['billing_vat'] ) ) {
update_user_meta( $user_id, 'billing_vat', sanitize_text_field( $_POST['billing_vat'] ) );
}
}
You can add more custom fields as per your need.
And yes you can add custom fields under my-account/edit-address/billing/ by using woocommerce_billing_fields filter hook.
So the code for this, should be like below:
/* Add field under my account billing */
add_filter( 'woocommerce_billing_fields', 'my_woocommerce_billing_fields' );
function my_woocommerce_billing_fields( $fields ) {
$user_id = get_current_user_id();
$user = get_userdata( $user_id );
if ( !$user ) return;
$fields['billing_vat'] = array(
'type' => 'text',
'label' => __('VAT', 'woocommerce'),
'placeholder' => _x('VAT Number', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row'),
'clear' => true,
'default' => get_user_meta( $user_id, 'billing_vat', true ) // assing default value if any
);
return $fields;
}
/* Format custom field to show on my account billing */
add_filter( 'woocommerce_my_account_my_address_formatted_address', 'custom_my_account_my_address_formatted_address', 10, 3 );
function custom_my_account_my_address_formatted_address( $fields, $customer_id, $name ) {
$fields['vat'] = get_user_meta( $customer_id, $name . '_vat', true );
return $fields;
}
/* Replace the key for custom field to show on my account billing */
add_filter( 'woocommerce_formatted_address_replacements', 'custom_formatted_address_replacements', 10, 2 );
function custom_formatted_address_replacements( $address, $args ) {
$address['{vat}'] = '';
if ( ! empty( $args['vat'] ) ) {
$address['{vat}'] = __( 'VAT Number', 'woocommerce' ) . ': ' . $args['vat'];
}
return $address;
}
add_filter( 'woocommerce_localisation_address_formats', 'custom_localisation_address_format' );
function custom_localisation_address_format( $formats ) {
foreach($formats as $key => $value) :
$formats[$key] .= "\n\n{vat}";
endforeach;
return $formats;
}