{"id":33587735,"url":"https://github.com/chinazagideon/trader-apis","last_synced_at":"2026-04-12T03:32:02.204Z","repository":{"id":321505380,"uuid":"1075591161","full_name":"chinazagideon/trader-apis","owner":"chinazagideon","description":"Laravel APIs event driven payment microservice system with API key middleware for resource authorization and tenant isolation.","archived":false,"fork":false,"pushed_at":"2025-11-25T12:32:09.000Z","size":1363,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-28T14:55:44.918Z","etag":null,"topics":["api","asynchronous","deploy","docker","events","gateway","laravel","microsevice","observability","outbox-pattern","payments","rest-api"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chinazagideon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-13T17:55:18.000Z","updated_at":"2025-11-25T12:32:12.000Z","dependencies_parsed_at":"2025-10-30T02:52:15.954Z","dependency_job_id":null,"html_url":"https://github.com/chinazagideon/trader-apis","commit_stats":null,"previous_names":["chinazagideon/trader-apis"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chinazagideon/trader-apis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinazagideon%2Ftrader-apis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinazagideon%2Ftrader-apis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinazagideon%2Ftrader-apis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinazagideon%2Ftrader-apis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chinazagideon","download_url":"https://codeload.github.com/chinazagideon/trader-apis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chinazagideon%2Ftrader-apis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27345800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-29T02:00:06.589Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","asynchronous","deploy","docker","events","gateway","laravel","microsevice","observability","outbox-pattern","payments","rest-api"],"created_at":"2025-11-29T10:01:29.342Z","updated_at":"2025-11-29T10:05:07.407Z","avatar_url":"https://github.com/chinazagideon.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Payment Service APIs - Laravel Microservice Application\n\nA Secured robust, event-driven payment microservices system API key middleware for resource authorization and tenant isolation. Built with a modular, event-driven architecture for scalability and maintainability.\n\n## Core Architecture Principles\n\nThis application follows three fundamental architectural patterns:\n\n1. **Module-Based Architecture** - Self-contained, auto-discovered modules\n2. **Contract-Based Dependency Injection** - Interface-driven service binding\n3. **Event-Driven Design** - Decoupled, configurable event processing\n\n---\n\n## Module Architecture\n\n### Auto-Discovery System\n\nModules are automatically discovered from the `src/Modules/` directory. Each module is self-contained with its own:\n- Service providers\n- Database migrations\n- Routes\n- Controllers, Services, Repositories\n- Configuration files\n- Event listeners\n\n**Module Structure:**\n```\nsrc/Modules/{ModuleName}/\n├── Contracts/              # Service interfaces\n├── Database/\n│   ├── Migrations/         # Module migrations\n│   ├── Seeders/           # Module seeders\n│   └── Models/            # Eloquent models\n├── Http/\n│   ├── Controllers/       # API controllers\n│   ├── Requests/         # Form validation\n│   └── Resources/        # API resources\n├── Providers/            # Service providers\n├── Repositories/         # Data access layer\n├── Services/            # Business logic\n├── Events/              # Domain events\n├── Listeners/           # Event listeners\n├── routes/\n│   └── api.php         # Module routes\n└── config/             # Module configuration\n```\n\n### Module Manager\n\nThe `ModuleManager` automatically discovers and registers modules:\n\n```php\n$moduleManager = app(ModuleManager::class);\n$modules = $moduleManager-\u003egetModules();\n$health = $moduleManager-\u003egetModuleHealth('User');\n```\n\n**Features:**\n- Auto-discovery of modules in `src/Modules/`\n- Service provider registration with priority support\n- Health status monitoring\n- Route and migration collection\n- Module configuration loading\n\n### Module Service Providers\n\nEach module extends `BaseModuleServiceProvider` which provides:\n- Automatic service registration\n- Module namespace resolution\n- Configuration merging\n- Policy registration\n\n**Example:**\n```php\nclass UserServiceProvider extends BaseModuleServiceProvider\n{\n    protected string $moduleNamespace = 'App\\\\Modules\\\\User';\n    protected array $configFiles = ['user'];\n\n    protected function registerServices(): void\n    {\n        // Bind interfaces to implementations\n        $this-\u003eapp-\u003ebind(UserServiceInterface::class, UserService::class);\n        $this-\u003eapp-\u003ebind(UserRepositoryInterface::class, UserRepository::class);\n    }\n}\n```\n\n---\n\n## Contracts \u0026 Interface Binding\n\n### Contract-Based Design\n\nAll services communicate through interfaces (contracts), enabling:\n- Easy testing with mocks\n- Implementation swapping\n- Clear service boundaries\n- Dependency inversion\n\n### Service Binding Pattern\n\nServices are bound to their interfaces in module service providers:\n\n```php\n// In UserServiceProvider\nprotected function registerServices(): void\n{\n    // Singleton binding\n    $this-\u003eapp-\u003esingleton(UserService::class);\n    \n    // Interface binding\n    $this-\u003eapp-\u003ebind(UserServiceInterface::class, UserService::class);\n    $this-\u003eapp-\u003ebind(UserRepositoryInterface::class, UserRepository::class);\n}\n```\n\n### Dependency Injection\n\nControllers and services receive dependencies via constructor injection:\n\n```php\nclass UserController extends Controller\n{\n    public function __construct(\n        private UserServiceInterface $userService\n    ) {}\n}\n```\n\n### Sub-Module Service Registry\n\nThe `SubModuleServiceRegistry` automatically discovers and registers services that implement `SubModuleServiceContract`:\n\n```php\n// Services implementing SubModuleServiceContract are auto-registered\nclass UserBalanceService implements SubModuleServiceContract\n{\n    public function getDefaultSubModuleName(): string\n    {\n        return 'user_balance';\n    }\n}\n\n// Access via registry\n$registry = app(SubModuleServiceRegistry::class);\n$service = $registry-\u003eget('user_balance');\n```\n\n---\n\n## Event-Driven Architecture\n\n### Event System Overview\n\nThe application uses a configurable event system that supports three processing modes:\n- **Sync** - Immediate processing\n- **Queue** - Background job processing\n- **Scheduled** - Batch processing via scheduled events table\n\n### Event Configuration\n\nEvents are configured in `config/events.php`:\n\n```php\n'events' =\u003e [\n    'investment_created' =\u003e [\n        'class' =\u003e InvestmentWasCreated::class,\n        'mode' =\u003e env('EVENT_INVESTMENT_MODE', 'queue'),\n        'queue' =\u003e env('EVENT_INVESTMENT_QUEUE', 'default'),\n        'priority' =\u003e 'high',\n        'listeners' =\u003e [\n            'create_transaction' =\u003e [\n                'class' =\u003e CreateTransactionForEntity::class,\n                'mode' =\u003e 'queue',\n                'tries' =\u003e 5,\n                'backoff' =\u003e [30, 60, 120],\n            ],\n        ],\n    ],\n],\n```\n\n### Notification Events Contract\n\nAll notification events implement `NotificationEventsContract`:\n\n```php\ninterface NotificationEventsContract\n{\n    public function getEntity();\n    public function getNotifiable();\n    public function getEventType(): string;\n    public function getChannels(): array;\n    public function getTitle(): string;\n    public function getMessage(): string;\n    // ... more methods\n}\n```\n\n### Base Notification Event\n\nEvents extend `BaseNotificationEvent`:\n\n```php\nclass UserWasCreatedEvent extends BaseNotificationEvent\n{\n    public function __construct(public User $user) {}\n\n    public function getEventType(): string\n    {\n        return 'user_was_created';\n    }\n\n    public function getEntity()\n    {\n        return $this-\u003euser;\n    }\n\n    public function getNotifiable()\n    {\n        return $this-\u003euser;\n    }\n\n    public function getChannels(): array\n    {\n        return ['database', 'mail'];\n    }\n}\n```\n\n### Configurable Listeners\n\nListeners implement `ConfigurableListenerInterface` to read configuration:\n\n```php\nclass SendEntityNotification implements ShouldQueue, ConfigurableListenerInterface\n{\n    use ConfigurableListener, InteractsWithQueue;\n\n    public function handle(NotificationEventsContract $event): void\n    {\n        // Listener reads its configuration from config/events.php\n        // Queue, retries, backoff all configured per listener\n    }\n}\n```\n\n### Event Dispatcher\n\nThe `EventDispatcher` service routes events based on configuration:\n\n```php\n$eventDispatcher-\u003edispatch(new InvestmentWasCreated($investment), 'investment_created');\n```\n\nThe dispatcher checks `config/events.php` to determine:\n- Processing mode (sync/queue/scheduled)\n- Queue name\n- Retry configuration\n- Priority\n\n---\n\n## Notification Outbox Pattern\n\n### Overview\n\nThe notification system uses an outbox pattern to ensure reliable notification delivery:\n\n1. **Event Fired** → Listener publishes to `notification_outbox` table\n2. **Outbox Processing** → Scheduled command processes pending notifications\n3. **Notification Delivery** → Creates database notifications and queues emails\n\n### Outbox Flow\n\n```\nEvent → Listener → NotificationOutboxPublisher → notification_outbox table\n                                                         ↓\n                                    ProcessNotificationOutbox Command\n                                                         ↓\n                                    Database Notification + Queued Email\n```\n\n### Outbox Table\n\nThe `notification_outbox` table stores pending notifications:\n\n- `event_type` - Type of event (e.g., 'user_was_created')\n- `notifiable_type` / `notifiable_id` - Who receives the notification\n- `entity_type` / `entity_id` - What triggered the notification\n- `channels` - Delivery channels (database, mail, sms)\n- `payload` - Notification data\n- `status` - pending|processing|sent|failed\n- `dedupe_key` - Prevents duplicate notifications\n\n### Processing Command\n\nThe `notifications:outbox:process` command runs via Laravel scheduler:\n\n```php\n// routes/console.php\nSchedule::command('notifications:outbox:process --limit=100')\n    -\u003eeveryMinute()\n    -\u003ewithoutOverlapping()\n    -\u003erunInBackground();\n```\n\n**Setup:**\n```bash\n# On server, add to crontab:\n* * * * * cd /var/www/trader-apis \u0026\u0026 docker exec trader-apis-app php artisan schedule:run\n```\n\n---\n\n## Module Management Commands\n\n### List Modules\n```bash\nphp artisan module:list\nphp artisan module:list --health\n```\n\n### Create Module\n```bash\nphp artisan module:create Product --description=\"Product management\"\n```\n\n### Migrations\n```bash\nphp artisan module:migrate User\nphp artisan module:migrate --all\nphp artisan module:rollback User\nphp artisan module:migration:status\n```\n\n### Cache Module Providers\n```bash\nphp artisan module:cache:providers\nphp artisan module:providers:list\n```\n\n---\n\n## API Gateway\n\n### Gateway Endpoints\n\n- `GET /api/gateway/status` - Gateway status\n- `GET /api/gateway/health` - Overall health check\n- `GET /api/gateway/modules` - All modules info\n- `GET /api/gateway/modules/{module}` - Specific module info\n\n### Module Routes\n\nEach module defines routes in `routes/api.php`:\n\n```php\nRoute::prefix('api/v1/users')-\u003egroup(function () {\n    Route::get('/', [UserController::class, 'index']);\n    Route::post('/', [UserController::class, 'store']);\n});\n```\n\n---\n\n## Database Architecture\n\n### Module Migrations\n\nEach module has its own migrations in `Database/Migrations/`. Migrations are automatically discovered and registered.\n\n### Morph Maps\n\nPolymorphic relationships use clean aliases via morph maps:\n\n```php\n// config/core.php\n'morph_maps' =\u003e [\n    'user' =\u003e \\App\\Modules\\User\\Database\\Models\\User::class,\n    'investment' =\u003e \\App\\Modules\\Investment\\Database\\Models\\Investment::class,\n]\n```\n\n### Database Connections\n\nModules can use separate database connections via configuration:\n\n```php\n// Module config\n'database' =\u003e [\n    'connection' =\u003e env('USER_DB_CONNECTION', 'default'),\n    'prefix' =\u003e env('USER_DB_PREFIX', ''),\n],\n```\n\n---\n\n## Current Modules\n\n- **Auth** - Authentication and authorization\n- **User** - User management\n- **Client** - Multi-client support\n- **Investment** - Investment management\n- **Transaction** - Transaction processing\n- **Payment** - Payment processing\n- **Funding** - Account funding\n- **Withdrawal** - Withdrawal processing\n- **Balance** - Balance management\n- **Notification** - Notification system\n- **Market** - Market data\n- **Pricing** - Pricing engine\n- **Currency** - Currency management\n- **Category** - Transaction categories\n- **Role** - Role-based access control\n- **Dashboard** - Dashboard data\n- **Swap** - Currency swapping\n\n---\n\n## Key Features\n\n### 1. Module Auto-Discovery\nModules are automatically discovered and registered on application boot.\n\n### 2. Contract-Based Services\nAll services use interfaces, enabling easy testing and implementation swapping.\n\n### 3. Configurable Event Processing\nEvents can be processed sync, queued, or scheduled based on configuration.\n\n### 4. Notification Outbox\nReliable notification delivery using the outbox pattern with scheduled processing.\n\n### 5. Sub-Module Services\nAutomatic registration of services implementing `SubModuleServiceContract`.\n\n### 6. Health Monitoring\nModule health checks via API Gateway endpoints.\n\n### 7. Module Migrations\nIsolated migrations per module with rollback support.\n\n---\n\n## Development Workflow\n\n### Creating a New Module\n\n1. Generate module structure:\n```bash\nphp artisan module:create Product\n```\n\n2. Define contracts in `Contracts/`:\n```php\ninterface ProductServiceInterface {}\n```\n\n3. Implement services:\n```php\nclass ProductService implements ProductServiceInterface {}\n```\n\n4. Bind in service provider:\n```php\n$this-\u003eapp-\u003ebind(ProductServiceInterface::class, ProductService::class);\n```\n\n5. Create events:\n```php\nclass ProductWasCreated extends BaseNotificationEvent {}\n```\n\n6. Register listeners in event service provider\n\n7. Add routes in `routes/api.php`\n\n8. Create migrations:\n```bash\nphp artisan module:make:migration Product create_products_table\n```\n\n---\n\n## Best Practices\n\n### Module Design\n- Keep modules focused on a single domain\n- Use contracts for all service interfaces\n- Minimize cross-module dependencies\n- Each module should be independently testable\n\n### Event Design\n- Events should represent domain events (things that happened)\n- Use descriptive event names (e.g., `UserWasCreated`, `InvestmentWasCreated`)\n- Events should contain all data needed by listeners\n- Store IDs, not full models, for serialization safety\n\n### Service Design\n- Services should implement interfaces\n- Use dependency injection, not facades\n- Keep services focused on business logic\n- Repositories handle data access\n\n### Testing\n- Mock interfaces, not concrete classes\n- Test modules in isolation\n- Use contracts for test doubles\n- Test event listeners separately\n\n---\n\n## Configuration\n\n### Module Configuration\n\nEach module can define `config/{module}.php`:\n\n```php\nreturn [\n    'module' =\u003e [\n        'name' =\u003e 'User',\n        'version' =\u003e '1.0.0',\n    ],\n    'database' =\u003e [\n        'connection' =\u003e env('USER_DB_CONNECTION', 'default'),\n    ],\n];\n```\n\n### Event Configuration\n\nEvents are configured in `config/events.php` with per-event and per-listener settings.\n\n### Notification Configuration\n\nNotification channels and providers configured in `config/notification.php`.\n\n---\n\nThis architecture provides a solid foundation for building scalable, maintainable applications with clear module boundaries and event-driven communication.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinazagideon%2Ftrader-apis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchinazagideon%2Ftrader-apis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchinazagideon%2Ftrader-apis/lists"}