Installation:
composer require djunehor/laravel-vtu
Publish the config file:
php artisan vendor:publish --provider="Djunehor\LaravelVtu\VtuServiceProvider"
Configure .env:
VTU_PROVIDER=africastalking # or 'mtn', 'glo', or a custom provider
VTU_AFRICASTALKING_API_KEY=your_api_key_here
First Use Case: Buy airtime via a controller:
use Djunehor\LaravelVtu\Facades\Vtu;
public function buyAirtime(Request $request) {
$response = Vtu::buyAirtime(
phoneNumber: '2348012345678',
amount: 500,
network: 'MTN'
);
return $response->success() ? 'Success!' : 'Failed: ' . $response->message();
}
config/vtu.php (provider settings, API keys, default values).Djunehor\LaravelVtu\Facades\Vtu (main entry point).app/Providers/VtuServiceProvider.php (custom provider registration).Provider Abstraction: Use the facade to switch providers dynamically:
// Default provider (from config)
Vtu::buyAirtime(...);
// Force a specific provider
Vtu::setProvider('glo')->buyAirtime(...);
Transaction Handling: Wrap VTU calls in transactions for financial safety:
DB::transaction(function () {
$user->deductBalance(500); // Your logic
$response = Vtu::buyAirtime($user->phone, 500, 'MTN');
if (!$response->success()) {
throw new \Exception($response->message());
}
});
Webhook Validation: Validate VTU webhooks in a middleware or controller:
public function handleWebhook(Request $request) {
$validation = Vtu::validateWebhook($request->all());
if ($validation->success()) {
// Process successful transaction
}
}
Custom Providers:
Extend Djunehor\LaravelVtu\Contracts\VtuProvider:
class CustomProvider implements VtuProvider {
public function buyAirtime($phone, $amount, $network) {
// Custom logic (e.g., API calls)
return new VtuResponse(true, 'Success', $data);
}
}
Register in config/vtu.php:
'providers' => [
'custom' => \App\Providers\CustomProvider::class,
],
\Log::info('VTU Response', $response->toArray());
BuyAirtimeJob::dispatch($phone, $amount, $network);
throttle middleware for VTU endpoints.Provider-Specific Quirks:
currency (e.g., NGN) and countryCode (e.g., 234).
Vtu::buyAirtime('2348012345678', 500, 'MTN', ['currency' => 'NGN', 'countryCode' => '234']);
destinationNumber formatted as 2348012345678 (without +).Webhook Delays: VTU providers may delay webhook delivery. Implement retry logic:
if (!$validation->success()) {
// Retry after 5 minutes
$this->retryAfter(300);
}
API Key Exposure:
Never hardcode keys in Blade or client-side JS. Use Laravel’s env() or encrypted config:
config('vtu.africastalking.api_key'); // Safe in PHP
Network Validation:
Some providers (e.g., Africastalking) ignore the network parameter. Validate responses:
if ($response->data->network !== 'MTN') {
throw new \Exception('Network mismatch');
}
dd($response->toArray());
400 for invalid phone).$this->app->bind(VtuProvider::class, function () {
return new MockProvider();
});
Custom Responses:
Extend Djunehor\LaravelVtu\VtuResponse for additional fields:
class ExtendedResponse extends VtuResponse {
public function getTransactionId() { ... }
}
Override the facade’s makeResponse() method.
Middleware for Auth: Protect VTU endpoints:
Route::middleware(['auth:sanctum', 'vtu.auth'])->post('/vtu/webhook');
Local Testing: Use a mock provider for local development:
'providers' => [
'local' => \Djunehor\LaravelVtu\Providers\MockProvider::class,
],
Configure in .env:
VTU_PROVIDER=local
How can I help you explore Laravel packages today?