Most codebases start clean, then slowly get messy in the same place: object creation inside business classes.
You write:
It works, until requirements change: mock the gateway for tests, switch notifier per user, add retries/logging, support a new provider. Now OrderService is doing two jobs: business logic and wiring dependencies. That tight coupling makes changes risky and testing painful.
The Dependency Injection (DI) Pattern fixes this by flipping control: instead of creating collaborators, a class receives them (usually via constructor). Your class depends on interfaces, and composition happens outside.