“Call to a member function have_posts() on array” error on have_posts();

Well, get_posts() returns an array, so you probably (made a typo and) meant to use new WP_Query there:

get_posts() returns an array of, by default, post objects (see WP_Post), and arrays do not have methods (functions in a PHP class), hence you can’t use the “arrow” on an array variable, and so that explains the error “Call to a member function have_posts() on array“.

$array = array( 1, 2, 3 );
$array->foo(); // error - $array is an array, not an object

class MyClass {
    public function foo() {
        echo 'it works';
    }
}
$object = new MyClass;
$object->foo(); // works - $object is an object (or a class instance) and the
                // method foo() exists and callable/public

And the have_posts() in question belongs in the WP_Query class, so you may want to do $custom_query = new WP_Query( [ <args> ] ) and not $custom_query = get_posts():

$custom_query = new WP_Query( [
    // your args here
] );

I hope that helps, and if you need further help with WP_Query, check out the documentation.