{"id":47928884,"url":"https://github.com/hamoi1/laravel-fib-payment","last_synced_at":"2026-04-08T11:00:31.832Z","repository":{"id":348569232,"uuid":"1198727364","full_name":"Hamoi1/laravel-fib-payment","owner":"Hamoi1","description":"Laravel package for integrating with the First Iraqi Bank (FIB) payment gateway, providing seamless payment processing and management","archived":false,"fork":false,"pushed_at":"2026-04-05T10:55:08.000Z","size":28,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-07T10:03:08.192Z","etag":null,"topics":["fib","first-iraqi-bank","gateway","integration","iqd","iraq","laravel","package","payment","payment-gateway","payment-integration","php"],"latest_commit_sha":null,"homepage":"https://fib.iq","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hamoi1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2026-04-01T17:44:15.000Z","updated_at":"2026-04-07T07:24:56.000Z","dependencies_parsed_at":"2026-04-06T09:00:35.139Z","dependency_job_id":null,"html_url":"https://github.com/Hamoi1/laravel-fib-payment","commit_stats":null,"previous_names":["hamoi1/laravel-fib-payment"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Hamoi1/laravel-fib-payment","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hamoi1%2Flaravel-fib-payment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hamoi1%2Flaravel-fib-payment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hamoi1%2Flaravel-fib-payment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hamoi1%2Flaravel-fib-payment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hamoi1","download_url":"https://codeload.github.com/Hamoi1/laravel-fib-payment/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hamoi1%2Flaravel-fib-payment/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31551891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T10:21:54.569Z","status":"ssl_error","status_checked_at":"2026-04-08T10:21:38.171Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["fib","first-iraqi-bank","gateway","integration","iqd","iraq","laravel","package","payment","payment-gateway","payment-integration","php"],"created_at":"2026-04-04T07:09:06.471Z","updated_at":"2026-04-08T11:00:31.745Z","avatar_url":"https://github.com/Hamoi1.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel FIB Payment (First Iraqi Bank)\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://packagist.org/packages/hamoi1/laravel-fib-payment\"\u003e\u003cimg src=\"https://img.shields.io/packagist/v/hamoi1/laravel-fib-payment.svg?style=flat-square\" alt=\"Latest Version on Packagist\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://packagist.org/packages/hamoi1/laravel-fib-payment\"\u003e\u003cimg src=\"https://img.shields.io/packagist/php-v/hamoi1/laravel-fib-payment.svg?style=flat-square\" alt=\"Supported PHP Version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://packagist.org/packages/hamoi1/laravel-fib-payment\"\u003e\u003cimg src=\"https://img.shields.io/badge/Laravel-11.x%20|%2012.x%20|%2013.x-orange?style=flat-square\" alt=\"Laravel Versions\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/packagist/l/hamoi1/laravel-fib-payment.svg?style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nA modern, type-safe Laravel SDK for First Iraqi Bank (FIB) payment integration. This package provides a fluent API for payment creation, status tracking, cancellations, refunds, and webhook protection with full dependency injection support.\n\n---\n\n## Table of Contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Configuration](#configuration)\n- [Architecture Overview](#architecture-overview)\n- [Usage](#usage)\n- [API Reference](#api-reference)\n- [Error Handling](#error-handling)\n- [Webhook Protection](#webhook-protection)\n- [Testing](#testing)\n- [Advanced Usage](#advanced-usage)\n- [Troubleshooting](#troubleshooting)\n- [License](#license)\n\n---\n\n## Requirements\n\n- PHP 8.2+\n- Laravel 11.x, 12.x, or 13.x\n- FIB Payment Gateway credentials (client_id and client_secret)\n\n---\n\n## Installation\n\nInstall via Composer:\n\n```bash\ncomposer require hamoi1/laravel-fib-payment\n```\n\nThe package will auto-register via Laravel's discovery. Publish the configuration file:\n\n```bash\nphp artisan vendor:publish --tag=fib-config\n```\n\n---\n\n## Configuration\n\nAdd the following to your `.env` file:\n\n```env\n# Required\nFIB_CLIENT_ID=your-fib-client-id\nFIB_CLIENT_SECRET=your-fib-client-secret\nFIB_ENVIRONMENT=stage\n\n# Optional\nFIB_CALLBACK_URL=https://your-app.test/fib/webhook\nFIB_CURRENCY=IQD\nFIB_TIMEOUT=15\nFIB_CONNECT_TIMEOUT=5\nFIB_RETRY_TIMES=3\nFIB_RETRY_DELAY=200\nFIB_CACHE_DRIVER=\nFIB_REFUNDABLE_FOR=P7D\nFIB_ALLOWED_CALLBACK_IPS=\n```\n\n### Environment Variables Reference\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `FIB_CLIENT_ID` | Yes | - | OAuth2 client ID from FIB |\n| `FIB_CLIENT_SECRET` | Yes | - | OAuth2 client secret from FIB |\n| `FIB_ENVIRONMENT` | Yes | `stage` | Environment: `stage`, or `prod` |\n| `FIB_CALLBACK_URL` | No | `http://127.0.0.1:8000/fib/callback` | Webhook endpoint for status updates |\n| `FIB_CURRENCY` | No | `IQD` | Default currency: `IQD` or `USD` |\n| `FIB_TIMEOUT` | No | `15` | HTTP request timeout in seconds |\n| `FIB_CONNECT_TIMEOUT` | No | `5` | Connection timeout in seconds |\n| `FIB_RETRY_TIMES` | No | `3` | Number of retry attempts for failed requests |\n| `FIB_RETRY_DELAY` | No | `200` | Delay between retries in milliseconds |\n| `FIB_CACHE_DRIVER` | No | - | Cache driver for OAuth tokens (null = default) |\n| `FIB_REFUNDABLE_FOR` | No | `P7D` | ISO 8601 duration for refund window |\n| `FIB_ALLOWED_CALLBACK_IPS` | No | - | Comma-separated IPs for webhook security |\n\n### Environments\n\n| Environment | Base URL | Use Case |\n|-------------|----------|----------|\n| `stage` | `https://fib.stage.fib.iq` | Testing with FIB staging apps |\n| `prod` | `https://fib.prod.fib.iq` | Production transactions |\n\n---\n\n## Architecture Overview\n\n### Design Principles\n\n- **Dependency Injection**: No static methods - everything is injectable\n- **Type Safety**: PHP 8.2+ features with `readonly` classes and strict types\n- **DTO Pattern**: Data Transfer Objects for all API inputs/outputs\n- **Enum Safety**: Enums for currencies, environments, statuses, and error reasons\n- **Exception Hierarchy**: Specific exceptions for different error types\n- **Token Caching**: Smart OAuth2 token caching with configurable drivers\n\n## Usage\n\n### 1. Quick Start with Facade\n\nThe simplest way to use the package:\n\n```php\nuse Hamoi1\\FibPayment\\Facades\\Fib;\nuse Hamoi1\\FibPayment\\Data\\PaymentRequest;\nuse Hamoi1\\FibPayment\\Enums\\Currency;\n\n// Create a payment\n$response = Fib::createPayment(new PaymentRequest(\n    amount: 25000,\n    currency: Currency::IQD,\n    description: 'Order #1024',\n    callbackUrl: route('fib.webhook'),\n));\n\n// Access response data\n$paymentId = $response-\u003epaymentId;\n$readableCode = $response-\u003ereadableCode;\n$qrCode = $response-\u003eqrCode;\n```\n\n### 2. Check Payment Status\n\n```php\nuse Hamoi1\\FibPayment\\Facades\\Fib;\n\n$status = Fib::getPaymentStatus($paymentId);\n\n// Helper methods\nif ($status-\u003eisPaid()) {\n    // Payment completed successfully\n    $payerName = $status-\u003epaidBy?-\u003ename;\n    $payerIban = $status-\u003epaidBy?-\u003eiban;\n}\n\nif ($status-\u003eisUnpaid()) {\n    // Payment still pending\n    $expiresAt = $status-\u003evalidUntil;\n}\n\nif ($status-\u003eisDeclined()) {\n    // Payment declined\n    $reason = $status-\u003edecliningReason?-\u003evalue;\n}\n```\n\n### 3. Cancel or Refund Payments\n\n```php\n// Cancel an unpaid payment\n$cancelled = Fib::cancelPayment($paymentId); // bool\n\n// Refund a paid payment (within refundable window)\n$refunded = Fib::refundPayment($paymentId); // bool\n```\n\n### 4. Dependency Injection (Recommended)\n\nFor better testability and cleaner architecture:\n\n```php\nuse Hamoi1\\FibPayment\\Contracts\\FibClientInterface;\nuse Hamoi1\\FibPayment\\Data\\PaymentRequest;\n\nfinal class CheckoutController\n{\n    public function __construct(\n        private readonly FibClientInterface $fib\n    ) {}\n\n    public function store(Request $request): JsonResponse\n    {\n        $payment = $this-\u003efib-\u003ecreatePayment(new PaymentRequest(\n            amount: $request-\u003einput('amount'),\n            description: \"Order #{$request-\u003einput('order_id')}\",\n        ));\n\n        return response()-\u003ejson([\n            'payment_id' =\u003e $payment-\u003epaymentId,\n            'code' =\u003e $payment-\u003ereadableCode,\n        ]);\n    }\n}\n```\n\n---\n\n\n## Error Handling\n\nThe package throws specific exceptions for different error scenarios:\n\n### Exception Hierarchy\n\n```\nFibException (abstract base)\n├── AuthenticationException (401/403)\n├── RateLimitException (429)\n└── PaymentFailedException (other HTTP errors)\n```\n\n### Handling Examples\n\n```php\nuse Hamoi1\\FibPayment\\Exceptions\\AuthenticationException;\nuse Hamoi1\\FibPayment\\Exceptions\\RateLimitException;\nuse Hamoi1\\FibPayment\\Exceptions\\PaymentFailedException;\nuse Hamoi1\\FibPayment\\Exceptions\\FibException;\n\ntry {\n    $response = Fib::createPayment($request);\n} catch (AuthenticationException $e) {\n    // Invalid credentials or token expired\n    // HTTP 401 or 403\n    Log::error('FIB auth failed: ' . $e-\u003egetMessage());\n} catch (RateLimitException $e) {\n    // Too many requests\n    // HTTP 429\n    Log::warning('FIB rate limit hit');\n    // Retry after delay\n} catch (PaymentFailedException $e) {\n    // Other API errors (500, 400, etc.)\n    Log::error('FIB payment error: ' . $e-\u003egetMessage());\n} catch (FibException $e) {\n    // Catch-all for any package exception\n    Log::error('FIB error: ' . $e-\u003egetMessage());\n}\n```\n\n---\n\n## Webhook Protection\n\n### Using the Middleware\n\nProtect your webhook endpoint from invalid requests:\n\n```php\nuse Hamoi1\\FibPayment\\Http\\Middleware\\VerifyFibWebhook;\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::post('/fib/webhook', [PaymentController::class, 'handleWebhook'])\n    -\u003emiddleware(VerifyFibWebhook::class)\n    -\u003ename('fib.webhook');\n```\n\n### Middleware Validation\n\nThe `VerifyFibWebhook` middleware validates:\n\n1. **Required Fields**: Ensures `paymentId` and `status` are present\n2. **Valid Status**: Checks status is one of `PAID`, `UNPAID`, or `DECLINED`\n3. **IP Allowlist**: If `FIB_ALLOWED_CALLBACK_IPS` is set, validates request IP\n\n### Webhook Controller Example\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\JsonResponse;\nuse Hamoi1\\FibPayment\\Enums\\PaymentStatus;\n\nfinal class PaymentController extends Controller\n{\n    public function handleWebhook(Request $request): JsonResponse\n    {\n        $paymentId = $request-\u003einput('paymentId');\n        $status = PaymentStatus::from($request-\u003einput('status'));\n\n        match ($status) {\n            PaymentStatus::PAID =\u003e $this-\u003emarkOrderAsPaid($paymentId),\n            PaymentStatus::DECLINED =\u003e $this-\u003emarkOrderAsDeclined($paymentId),\n            PaymentStatus::UNPAID =\u003e null, // No action needed\n        };\n\n        return response()-\u003ejson(['received' =\u003e true]);\n    }\n\n    private function markOrderAsPaid(string $paymentId): void\n    {\n        // Update your database\n        Order::where('fib_payment_id', $paymentId)\n            -\u003eupdate(['status' =\u003e 'paid']);\n    }\n\n    private function markOrderAsDeclined(string $paymentId): void\n    {\n        Order::where('fib_payment_id', $paymentId)\n            -\u003eupdate(['status' =\u003e 'declined']);\n    }\n}\n```\n\n### IP Allowlist Configuration\n\nRestrict webhooks to specific FIB server IPs:\n\n```env\nFIB_ALLOWED_CALLBACK_IPS=203.0.113.10,203.0.113.11\n```\n\n---\n\n## Testing\n\n### Mocking the Service\n\nIn your application tests, mock the interface:\n\n```php\nuse Hamoi1\\FibPayment\\Contracts\\FibClientInterface;\nuse Hamoi1\\FibPayment\\Data\\PaymentResponse;\nuse Hamoi1\\FibPayment\\Data\\PaymentStatusInfo;\nuse Hamoi1\\FibPayment\\Enums\\PaymentStatus;\nuse Illuminate\\Support\\Facades\\App;\nuse Mockery;\n\nit('processes successful payment', function () {\n    // Create mock\n    $mock = Mockery::mock(FibClientInterface::class);\n\n    // Define expected behavior\n    $mock-\u003eshouldReceive('createPayment')\n        -\u003eonce()\n        -\u003eandReturn(new PaymentResponse(\n            paymentId: 'pay-test-123',\n            readableCode: 'ABC123',\n            qrCode: 'base64-encoded-qr-data',\n            validUntil: now()-\u003eaddHour()-\u003etoIso8601String(),\n            personalAppLink: 'https://fib.iq/personal/pay-test-123',\n            businessAppLink: 'https://fib.iq/business/pay-test-123',\n            corporateAppLink: 'https://fib.iq/corporate/pay-test-123',\n        ));\n\n    // Bind mock to container\n    App::instance(FibClientInterface::class, $mock);\n\n    // Test your controller/service\n    $response = $this-\u003epostJson('/api/checkout', [\n        'amount' =\u003e 1000,\n    ]);\n\n    $response-\u003eassertOk()\n        -\u003eassertJsonPath('payment_id', 'pay-test-123');\n});\n\nit('handles paid webhook', function () {\n    $mock = Mockery::mock(FibClientInterface::class);\n    \n    $mock-\u003eshouldReceive('getPaymentStatus')\n        -\u003ewith('pay-test-456')\n        -\u003eandReturn(new PaymentStatusInfo(\n            paymentId: 'pay-test-456',\n            status: PaymentStatus::PAID,\n            validUntil: now()-\u003eaddHour()-\u003etoIso8601String(),\n            amount: new \\Hamoi1\\FibPayment\\Data\\MonetaryValue(1000, \\Hamoi1\\FibPayment\\Enums\\Currency::IQD),\n        ));\n\n    App::instance(FibClientInterface::class, $mock);\n\n    $response = $this-\u003epostJson('/fib/webhook', [\n        'paymentId' =\u003e 'pay-test-456',\n        'status' =\u003e 'PAID',\n    ]);\n\n    $response-\u003eassertOk();\n});\n```\n\n### Package Quality Commands\n\nRun these commands to ensure code quality:\n\n```bash\n# Run all checks\ncomposer check\n\n# Individual commands\ncomposer lint      # Laravel Pint code style check\ncomposer lint:fix  # Auto-fix code style\ncomposer analyse   # PHPStan static analysis\ncomposer test      # Pest tests\n```\n\n---\n\n## Troubleshooting\n\n### Common Issues\n\n| Issue | Solution |\n|-------|----------|\n| `Jwt issuer is not configured` | Your client_id isn't activated by FIB. Contact FIB support. |\n| `401 Unauthorized` | Check client_id and client_secret in .env |\n| `403 Forbidden` | Credentials may be valid but lack permissions |\n| `429 Too Many Requests` | You're hitting rate limits. Implement exponential backoff. |\n| Token cache issues | Run `php artisan cache:clear` |\n| Config not loading | Run `php artisan config:clear` |\n\n### Debug Endpoints\n\nAdd this to your routes for debugging:\n\n```php\nRoute::get('/fib/debug', function () {\n    return [\n        'environment' =\u003e config('fib.environment'),\n        'client_id' =\u003e config('fib.client_id') ? '***' . substr(config('fib.client_id'), -4) : 'NOT SET',\n        'client_secret_set' =\u003e ! empty(config('fib.client_secret')),\n        'callback_url' =\u003e config('fib.callback_url'),\n        'base_url' =\u003e \\Hamoi1\\FibPayment\\Enums\\FibEnvironment::from(config('fib.environment'))-\u003ebaseUrl(),\n    ];\n});\n```\n\n---\n\n## License\n\nThe MIT License (MIT). Please see [LICENSE](LICENSE) for more information.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhamoi1%2Flaravel-fib-payment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhamoi1%2Flaravel-fib-payment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhamoi1%2Flaravel-fib-payment/lists"}