matt-di / laravel-telebirr
Telebirr payment gateway integration for Laravel applications
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 1
pkg:composer/matt-di/laravel-telebirr
Requires
- php: ^8.1
- illuminate/cache: ^9.0|^10.0|^11.0
- illuminate/events: ^9.0|^10.0|^11.0
- illuminate/http: ^9.0|^10.0|^11.0
- illuminate/queue: ^9.0|^10.0|^11.0
- illuminate/support: ^9.0|^10.0|^11.0
- laravel/framework: ^9.0|^10.0|^11.0
- phpseclib/phpseclib: ^3.0
Requires (Dev)
- mockery/mockery: ^1.4
- orchestra/testbench: ^7.0|^8.0|^9.0
- phpstan/phpstan: ^1.0
- phpunit/phpunit: ^9.0|^10.0
This package is not auto-updated.
Last update: 2026-01-10 17:44:53 UTC
README
Telebirr payment gateway integration for Laravel applications with support for single and multi-merchant setups.
🎯 Integration Type
This package is designed for Telebirr Super App integration where the frontend handles payment requests through the Telebirr mobile application.
- Backend Role: Generates signed payment requests and handles webhooks
- Frontend Role: Uses Telebirr mobile SDK to process payments
- 📖 Frontend Integration: Refer to Telebirr Developer Documentation for mobile app integration details
- 🔗 Official Resources: Check Telebirr's official documentation for SDK implementation and best practices
Features
- 🚀 Simple Setup - Get started in minutes with zero configuration
- 🏪 Multi-Merchant Support - Perfect for multi-branch or multi-store applications
- 🔐 Enterprise Security - RSA PSS signatures, webhook verification, SSL controls
- ⚡ High Performance - Token caching, queue-based processing, retry logic
- 🛠 Developer Friendly - Artisan commands, comprehensive logging, extensive configuration
- 🔧 Highly Configurable - Extensive customization options for any use case
- 📱 Mobile SDK Ready - Raw request generation for Telebirr mobile applications
- 🎯 Event Driven - Laravel events for payment lifecycle hooks
Installation
Basic Setup (Single Merchant)
composer require matt-di/laravel-telebirr php artisan telebirr:install
Multi-Merchant Setup
composer require Matt-di/laravel-telebirr php artisan telebirr:install --mode=multi --run-migrations
Quick Start
1. Configure Environment
Add your Telebirr credentials to .env:
# Single merchant mode TELEBIRR_MODE=single TELEBIRR_FABRIC_APP_ID=your_fabric_app_id TELEBIRR_MERCHANT_APP_ID=your_merchant_app_id TELEBIRR_MERCHANT_CODE=123456 TELEBIRR_APP_SECRET=your_app_secret TELEBIRR_RSA_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
2. Create Payment Request
use Telebirr\LaravelTelebirr\Facades\Telebirr; $rawRequest = Telebirr::initiatePayment([ 'txn_ref' => 'TXN_' . time(), 'amount' => 150.00, 'subject' => 'Order Payment' ]); // Returns: "appid=MERCHANT123&merch_code=MC456&nonce_str=abc...&prepay_id=PRE123...×tamp=202512021200&sign_type=SHA256WithRSA&sign=signed_data..."
3. Handle Webhook (Automatically Done)
The package handles webhook verification, signature checking, and payment verification automatically.
Usage Examples
Single Merchant
// Simple payment initiation Telebirr::initiatePayment([ 'txn_ref' => 'TXN_123', 'amount' => 100.00, 'subject' => 'Product Purchase' ]);
Multi-Merchant (Branch-Based)
// Payment for specific branch Telebirr::initiatePayment([ 'txn_ref' => 'TXN_123', 'amount' => 100.00, 'subject' => 'Branch Order' ], ['branch_id' => 1]);
Custom Context
// Organized by stores Telebirr::initiatePayment($data, ['store_id' => 5]); // Or even custom types Telebirr::initiatePayment($data, ['owner_type' => 'restaurant', 'owner_id' => 10]);
Payment Verification
$result = Telebirr::verifyPayment('TXN_123'); if ($result && $result['order_status'] === 'PAY_SUCCESS') { // Payment successful }
Auth Token Retrieval
$userInfo = Telebirr::getAuthToken($accessToken);
Error Handling
try { $paymentRequest = Telebirr::initiatePayment([ 'txn_ref' => 'TXN_' . time(), 'amount' => 150.00, 'subject' => 'Order Payment', ]); // Process successful payment initiation } catch (\Telebirr\LaravelTelebirr\Exceptions\TelebirrException $e) { // Handle payment initiation errors Log::error('Telebirr payment failed: ' . $e->getMessage()); // Show user-friendly error message return back()->withErrors(['payment' => 'Payment initiation failed. Please try again.']); }
Event Listeners
Listen to payment lifecycle events:
Event::listen(Telebirr\LaravelTelebirr\Events\PaymentInitiated::class, function ($event) { // Payment initiated }); Event::listen(Telebirr\LaravelTelebirr\Events\PaymentVerified::class, function ($event) { // Payment verified and successful // Update your order/invoice status here }); Event::listen(Telebirr\LaravelTelebirr\Events\WebhookReceived::class, function ($event) { // Raw webhook received });
Testing
Test your integration:
# Test API connectivity php artisan telebirr:test-connection # Setup and test webhooks php artisan telebirr:setup-webhook --test
Configuration
Single Merchant Mode
- Uses global ENV configuration
- No database required
- Perfect for simple applications
Multi-Merchant Mode
- Database-driven merchant management
- Configurable relationship mappings
- Enterprise-ready for complex applications
API Reference
Facade Methods
Telebirr::initiatePayment(array $data, array $context = []) Telebirr::verifyPayment(string $transactionId, array $context = []) Telebirr::queryOrder(string $orderId, array $context = []) Telebirr::getAuthToken(string $accessToken, array $context = []) Telebirr::handleWebhook(Request $request)
HTTP Endpoints
POST /api/telebirr/order- Create payment orderPOST /api/telebirr/verify- Verify payment statusPOST /api/telebirr/query- Query order detailsPOST /api/telebirr/auth- Get auth tokenPOST /api/telebirr/webhook- Webhook handler
Advanced Configuration
Publish config for full customization:
php artisan vendor:publish --tag=telebirr-config
Custom Merchant Resolver
// config/telebirr.php 'merchant' => [ 'resolver' => App\Services\CustomMerchantResolver::class, ],
Custom Webhook Handler
'webhook' => [ 'handler' => App\Services\CustomWebhookHandler::class, ],
Migration Guide
From Single to Multi-Merchant
- Change mode:
TELEBIRR_MODE=multi - Run:
php artisan telebirr:install --mode=multi --run-migrations - Add merchant records to
telebirr_merchantstable - Update code to pass merchant context where needed
Complete Integration Example
Here's a complete real-world integration example:
<?php namespace App\Http\Controllers; use App\Models\Order; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Telebirr\LaravelTelebirr\Facades\Telebirr; use Telebirr\LaravelTelebirr\Exceptions\TelebirrException; class PaymentController extends Controller { /** * Create payment order and initiate Telebirr payment */ public function checkout(Request $request) { $request->validate([ 'amount' => 'required|numeric|min:1|max:10000', 'description' => 'required|string|max:255', ]); // 1. Create order in your system first $order = Order::create([ 'user_id' => auth()->id(), 'amount' => $request->amount, 'currency' => 'ETB', 'description' => $request->description, 'status' => 'pending', 'reference' => 'ORD_' . time() . '_' . auth()->id(), ]); try { // 2. Initiate Telebirr payment $paymentRequest = Telebirr::initiatePayment([ 'txn_ref' => $order->reference, 'amount' => $order->amount, 'subject' => 'Order #' . $order->id, 'description' => $order->description, 'notify_url' => route('webhook.telebirr'), 'return_url' => route('payment.success', $order->id), 'timeout_express' => '30m', ]); // 3. Update order with payment request details $order->update([ 'payment_raw_request' => $paymentRequest, 'raw_request_parsed' => $this->parseRawRequest($paymentRequest), ]); Log::info('Telebirr payment initiated', [ 'order_id' => $order->id, 'amount' => $order->amount, 'payment_ref' => $order->reference ]); return response()->json([ 'success' => true, 'payment_raw_request' => $paymentRequest, 'order_id' => $order->id, 'reference' => $order->reference ]); } catch (TelebirrException $e) { // 4. Handle payment initiation failure $order->update(['status' => 'failed']); Log::error('Telebirr payment initiation failed', [ 'order_id' => $order->id, 'error' => $e->getMessage() ]); return response()->json([ 'success' => false, 'message' => 'Payment initiation failed. Please try again.', 'error' => $e->getMessage() ], 422); } } /** * Handle Telebirr webhooks */ public function webhook(Request $request) { try { $payload = $request->all(); // Verify webhook and process payment $result = Telebirr::handleWebhook($request); if ($result && isset($payload['merch_order_id'])) { // Update order status based on payment result $order = Order::where('reference', $payload['merch_order_id'])->first(); if ($order) { if ($payload['trade_status'] === 'Completed') { $order->update([ 'status' => 'paid', 'paid_at' => now(), 'payment_details' => $payload ]); Log::info('Order marked as paid', [ 'order_id' => $order->id, 'payment_ref' => $payload['merch_order_id'] ]); } elseif ($payload['trade_status'] === 'Failed') { $order->update([ 'status' => 'failed', 'payment_details' => $payload ]); Log::warning('Payment failed', [ 'order_id' => $order->id, 'payment_ref' => $payload['merch_order_id'] ]); } } } return response()->json(['code' => 0, 'message' => 'Success']); } catch (\Exception $e) { Log::error('Webhook processing failed', [ 'error' => $e->getMessage(), 'payload' => $request->all() ]); return response()->json(['code' => 1, 'message' => 'Processing failed'], 500); } } /** * Payment success page */ public function success(Order $order) { // Verify final payment status try { $result = Telebirr::verifyPayment($order->reference); if ($result && $result['order_status'] === 'PAY_SUCCESS') { $order->update([ 'status' => 'paid', 'verified_at' => now() ]); return view('payment.success', compact('order')); } else { return view('payment.pending', compact('order')); } } catch (TelebirrException $e) { Log::error('Payment verification failed', [ 'order_id' => $order->id, 'error' => $e->getMessage() ]); return view('payment.error', [ 'order' => $order, 'error' => 'Unable to verify payment status' ]); } } }
Troubleshooting
Common Issues
RSA Key Format Error
# Ensure your private key includes proper PEM headers
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7VITN...
-----END PRIVATE KEY-----
Network Timeouts
# Increase timeout in config or .env TELEBIRR_API_TIMEOUT=30
Webhook Signature Verification Failures
# Test webhook locally first php artisan telebirr:setup-webhook --url=https://your-domain.com/api/telebirr/webhook --test # Check your public/private key pair php artisan telebirr:test-connection
Multi-Merchant Configuration Issues
# Ensure merchant records exist php artisan tinker >>> App\Models\TelebirrMerchant::count() >>> App\Models\TelebirrMerchant::first() # Test with merchant context Telebirr::initiatePayment($data, ['store_id' => 1])
Database Connection Issues
# Run migrations for multi-merchant mode
php artisan migrate
php artisan telebirr:install --run-migrations
Queue Configuration for Background Processing
# Ensure queue is configured for payment verification QUEUE_CONNECTION=database TELEBIRR_QUEUE_VERIFY_PAYMENT_ENABLED=true
Debug Mode
Enable detailed logging for troubleshooting:
LOG_LEVEL=debug TELEBIRR_LOGGING_ENABLED=true
Getting Help
- Check logs:
storage/logs/laravel.log - Review network requests in browser dev tools
- Test API credentials manually with Postman
- Verify webhook endpoint is publicly accessible
Security
- RSA PSS signature validation
- Webhook signature verification with timestamp tolerance
- SSL certificate validation (configurable)
- Comprehensive audit logging
- Configurable sensitive data masking
Performance
- Fabric token caching (55-minute TTL)
- Queue-based payment verification
- Retry logic with exponential backoff
- Database connection pooling aware
- Optimized queries with proper indexing
Requirements
- PHP 8.1+
- Laravel 9.0+
- phpseclib 3.0+
Contributing
Please see CONTRIBUTING for details.
License
This package is open-sourced software licensed under the MIT license.
Support
- 📖 Documentation: https://laravel-telebirr.com
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions