My primary concern with this is that you built a network service that was based on ObservableObject and @Published. In order words, you succeeded in separating the service from your SwiftUI view... but you still made it dependent on SwiftUI.
If I were to do this I'd make the network service a plain class (or even a struct) where fetchProducts either was an async function that actually returned the data, or returned a Combine publisher.
That would allow it to be used with SwiftUI views... or with a view model, from within a repository, or even easily consumed by a UIKit component.
It would also allow you to easily base it on a protocol and create mocks for previews and testing should you desire. (Or should requirements change.)