Leverkusen started with a bang, pressing its visitors relentlessly, and Moussa Diaby had already fired over after a mistake by Axel Witsel, when Raphael Guerreiro conceded possession in his own half to pave the way for the opening goal.
Paulinho helped the ball on for Florian Wirtz, who drove into the heart of the Dortmund defence and dinked the ball beyond Gregor Kobel to score on nine minutes.
Lukas Hradecky denied former Leverkusen midfielder Julian Brandt a near carbon-copy equaliser, before Guerreiro intervened at the other end to block Schick at point-blank range.
Haaland headed in Thomas Meunier's right-wing cross to level matters on 37 minutes, with the same duo combining to set up Jude Bellingham moments later. The English teenager's effort was ruled out after a video assistant referee (VAR) review, though, because of an earlier foul by Mahmoud Dahoud.
Bayer got its nose in front on the stroke of half-time, courtesy of another Dortmund mistake in midfield, this time from Brandt. After being set free by Kerem Demirbay, Wirtz duly played in Schick, who side-footed a superb first-time finish.
Brandt atoned early in the second period with an excellent run, touch and finish, only for Diaby to restore Leverkusen's lead eight minutes later. The Frenchman completely miscued his first shot after a half-cleared corner, but dispatched from 18 yards at the second attempt.
Guerreiro responded with a sensational free-kick, before Dortmund forged ahead for the first time. VAR adjudged Odlion Kossounou to have raised an arm to the face of Marco Reus in the box, and Haaland made no mistake from the spot.
Dortmund was largely untroubled in the closing stages, holding out to climb above Gerardo Seoane's previously unbeaten Werkself in the standings.