Service Provider
PaymentsServiceProvider binds PaymentsManager into Magic's container under 'payments' and resolves the build's billing driver at boot.
On this page
Overview#
PaymentsServiceProvider extends Magic's ServiceProvider, the base class every plugin extends. It owns two things: the 'payments' container binding and the boot-time resolution of the driver this build serves.
class PaymentsServiceProvider extends ServiceProvider {
PaymentsServiceProvider(super.app);
@override
void register() { /* ... */ }
@override
Future<void> boot() async { /* ... */ }
}
Two-Phase Bootstrap Pattern#
| Phase | Method | Timing | Purpose |
|---|---|---|---|
| 1 | register() |
Synchronous, early | Bind services into the container |
| 2 | boot() |
Async, after every provider has registered | Do anything that depends on another binding |
register() runs for every provider before boot() runs for any of them, and Magic.init loads the config factories before either, so Config is populated by the time this provider boots.
register(): IoC Binding#
register() does exactly one thing: bind the PaymentsManager singleton under the 'payments' key. It reads no config and resolves no driver; both belong to boot(), because a driver resolved while other providers are still registering would be resolved against a half-built container.
app.singleton('payments', () => PaymentsManager());
After registration, any code in the app can resolve the manager by key:
final PaymentsManager manager = app.make<PaymentsManager>('payments');
boot(): Resolving the Platform Driver#
boot() runs three steps, in this order:
- It resolves the manager through the container, which proves that
register()bound what a consumer will resolve. - It reads
payments.driver. Absent or empty means the platform driver. Any value other than'platform'is logged at error level and ignored, because a config typo must not take an entitlement read offline. - It reads
PaymentsManager.billing, which makes the package's conditional-import factory resolve the driver for this build, and logs at debug level which implementation answered and whether the web rail and the store rail are present.
boot() does not decide where a subscription is managed and never asks kIsWeb or Platform.is; the factory answers what the build is capable of, and the entitlement's manageVia answers where a subscription is managed. See Drivers for what each arm of the factory returns.
Config Root#
The provider reads only under payments.*, never under magic_starter.* or any other plugin's root. A plugin that read another plugin's key would stop working the moment it was installed without that plugin. The keys are listed in Configuration.
Registering the Provider#
payments:install adds the provider to lib/config/app.dart for you. By hand:
import 'package:magic_payments/magic_payments.dart';
final providers = [
// ... other framework providers
(app) => PaymentsServiceProvider(app),
];
The order inside the list does not matter to this provider's own boot. The five reads and the web rail call the Http facade when you use them, so the app's network provider has to be registered somewhere in the same list.
Related Documentation#
- Payments Manager: the singleton this provider binds.
- Configuration: the
payments.*keys. - Drivers: the conditional-import factory behind
boot(). - Service Providers: how Magic registers and boots providers.