Shortcodes in billing fields doesn’t work

The “official” answer is that you need to use do_shortcode() to process the shortcode as you can’t just simply apply a shortcode within the code. Here’s your original code with the “official” do_shortcode() way:

 add_filter( 'woocommerce_checkout_fields', 'set_checkout_field_input_value_default' );

function set_checkout_field_input_value_default($fields) {
    $fields['billing']['billing_city']['default'] = do_shortcode( '[geoip_detect2 property="city"]' );
    $fields['billing']['billing_state']['default'] = do_shortcode( '[geoip_detect2 property="mostSpecificSubdivision"]' );
    return $fields;
}

While that approach will parse the shortcode, I personally would suggest that you NOT use do_shortcode() because it has to run through a fairly extensive regex to process. It’s better to find the actual callback function for the shortcode in question and use that directly. Yes, sometimes that is difficult, and is tricky in some situations. But thankfully, there’s a good article and a better solution at this link.

So here’s how to do it the J.D. Grimes way (as discussed in the article, and including his utility function along with your code snippet revised to use it):

/**
 * Call a shortcode function by tag name.
 *
 * @author J.D. Grimes
 * @link https://codesymphony.co/dont-do_shortcode/
 *
 * @param string $tag     The shortcode whose function to call.
 * @param array  $atts    The attributes to pass to the shortcode function. Optional.
 * @param array  $content The shortcode's content. Default is null (none).
 *
 * @return string|bool False on failure, the result of the shortcode on success.
 */
function do_shortcode_func( $tag, array $atts = array(), $content = null ) {

    global $shortcode_tags;

    if ( ! isset( $shortcode_tags[ $tag ] ) )
        return false;

    return call_user_func( $shortcode_tags[ $tag ], $atts, $content, $tag );
}

add_filter( 'woocommerce_checkout_fields', 'set_checkout_field_input_value_default' );

function set_checkout_field_input_value_default($fields) {
    $fields['billing']['billing_city']['default'] = do_shortcode_func( 'geoip_detect2', array( 'property' => "city" ) );
    $fields['billing']['billing_state']['default'] = do_shortcode_func( 'geoip_detect2', array( 'property' => "mostSpecificSubdivision" ) );
    return $fields;
}

Either way is “right” and should solve the issue (at least as far as the shortcode parsing goes). Hope this helps you.