Shortcode “post_per_page” not working

You have the posts_per_page attribute in your shortcode, but you’re not actually calling it in your WP_Query. Your’re doing a few unnecessary things in your code, but for now, the issue at hand is that you need to add:

if( !empty( $posts_per_page )) {
    $query .= '&posts_per_page=".$posts_per_page;
}

Before you call:

$wp_query->query($query);

As it is currently written, your query doesn”t take into the posts_per_page parameter into account