khalti / php-sdk
PHP SDK for Khalti Payment Gateway - Web Checkout (KPG-2) API
Installs: 50
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/khalti/php-sdk
Requires
- php: >=7.2
- ext-curl: *
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^8.0
- squizlabs/php_codesniffer: ^3.5
README
A simple and powerful PHP SDK for integrating Khalti Payment Gateway Web Checkout (KPG-2) API into your PHP applications.
🚀 Quick Start
Installation
composer require khalti/php-sdk
Basic Usage
<?php require_once 'vendor/autoload.php'; use KhaltiSDK\Khalti; use KhaltiSDK\Exceptions\ApiException; use KhaltiSDK\Exceptions\ValidationException; // Initialize SDK $khalti = new Khalti([ 'environment' => 'sandbox', // or 'live' for production 'secretKey' => 'your_secret_key_here', 'enableLogging' => true ]); // Initiate Payment try { $response = $khalti->ePayment()->initiate([ 'return_url' => 'https://yoursite.com/success', 'website_url' => 'https://yoursite.com', 'amount' => 1000, // 10 NPR in paisa 'purchase_order_id' => 'ORDER-123', 'purchase_order_name' => 'Test Product', 'customer_info' => [ 'name' => 'John Doe', 'email' => 'john@example.com', 'phone' => '9800000000' ] ]); // Redirect user to payment URL header('Location: ' . $response['payment_url']); exit; } catch (ValidationException $e) { echo "Error: " . $e->getMessage(); } catch (ApiException $e) { echo "API Error: " . $e->getMessage(); }
Verify Payment
<?php // After user returns from payment $pidx = $_GET['pidx']; try { $result = $khalti->ePayment()->verify($pidx); if ($result['status'] === 'Completed') { echo "Payment successful!"; // Update your database, send confirmation email, etc. } else { echo "Payment failed or pending"; } } catch (Exception $e) { echo "Verification failed: " . $e->getMessage(); }
🔧 Configuration
Sandbox Setup
-
Get Sandbox Credentials:
- Visit test-admin.khalti.com
- Sign up for a merchant account
- Use OTP:
987654for sandbox login - Get your
live_secret_keyfrom the dashboard
-
Update Your Code:
$khalti = new Khalti([ 'environment' => 'sandbox', 'secretKey' => 'live_secret_key_from_sandbox_dashboard', 'enableLogging' => true ]);
-
Test Credentials:
- Phone:
9800000001 - MPIN:
1111 - OTP:
987654
- Phone:
Production Setup
-
Get Production Credentials:
- Visit admin.khalti.com
- Complete merchant verification
- Get your production
live_secret_key
-
Update Your Code:
$khalti = new Khalti([ 'environment' => 'live', 'secretKey' => 'live_secret_key_from_production_dashboard', 'enableLogging' => false // Disable logging in production ]);
📝 Complete Example
Payment Initiation (initiate.php)
<?php require_once 'vendor/autoload.php'; use KhaltiSDK\Khalti; use KhaltiSDK\Exceptions\ApiException; use KhaltiSDK\Exceptions\ValidationException; $khalti = new Khalti([ 'environment' => 'sandbox', 'secretKey' => 'your_secret_key_here', 'enableLogging' => true ]); if ($_POST) { try { $response = $khalti->ePayment()->initiate([ 'return_url' => 'http://' . $_SERVER['HTTP_HOST'] . '/verify.php', 'website_url' => 'http://' . $_SERVER['HTTP_HOST'], 'amount' => (int)($_POST['amount'] * 100), 'purchase_order_id' => 'ORDER-' . time(), 'purchase_order_name' => $_POST['product_name'], 'customer_info' => [ 'name' => $_POST['customer_name'], 'email' => $_POST['customer_email'], 'phone' => $_POST['customer_phone'] ] ]); header('Location: ' . $response['payment_url']); exit; } catch (Exception $e) { $error = $e->getMessage(); } } ?> <!DOCTYPE html> <html> <head> <title>Khalti Payment</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="bg-gray-100 p-8"> <div class="max-w-md mx-auto bg-white rounded-lg shadow-md p-6"> <h1 class="text-2xl font-bold mb-6 text-center">Pay with Khalti</h1> <?php if (isset($error)): ?> <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4"> <?php echo htmlspecialchars($error); ?> </div> <?php endif; ?> <form method="POST"> <div class="mb-4"> <label class="block text-gray-700 text-sm font-bold mb-2">Product Name</label> <input type="text" name="product_name" value="Test Product" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:border-blue-500" required> </div> <div class="mb-4"> <label class="block text-gray-700 text-sm font-bold mb-2">Amount (NPR)</label> <input type="number" name="amount" value="10" min="10" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:border-blue-500" required> </div> <div class="mb-4"> <label class="block text-gray-700 text-sm font-bold mb-2">Customer Name</label> <input type="text" name="customer_name" value="John Doe" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:border-blue-500" required> </div> <div class="mb-4"> <label class="block text-gray-700 text-sm font-bold mb-2">Email</label> <input type="email" name="customer_email" value="john@example.com" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:border-blue-500" required> </div> <div class="mb-6"> <label class="block text-gray-700 text-sm font-bold mb-2">Phone</label> <input type="text" name="customer_phone" value="9800000001" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:border-blue-500" required> </div> <button type="submit" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded-lg"> Pay with Khalti </button> </form> </div> </body> </html>
Payment Verification (verify.php)
<?php require_once 'vendor/autoload.php'; use KhaltiSDK\Khalti; use KhaltiSDK\Exceptions\ApiException; $khalti = new Khalti([ 'environment' => 'sandbox', 'secretKey' => 'your_secret_key_here', 'enableLogging' => true ]); $pidx = $_GET['pidx'] ?? ''; if ($pidx) { try { $result = $khalti->ePayment()->verify($pidx); if ($result['status'] === 'Completed') { $message = "Payment successful! Transaction ID: " . $result['transaction_id']; $status = 'success'; } else { $message = "Payment status: " . $result['status']; $status = 'warning'; } } catch (Exception $e) { $message = "Verification failed: " . $e->getMessage(); $status = 'error'; } } else { $message = "No payment ID provided"; $status = 'error'; } ?> <!DOCTYPE html> <html> <head> <title>Payment Result</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="bg-gray-100 p-8"> <div class="max-w-md mx-auto bg-white rounded-lg shadow-md p-6"> <h1 class="text-2xl font-bold mb-6 text-center">Payment Result</h1> <div class="bg-<?php echo $status === 'success' ? 'green' : ($status === 'warning' ? 'yellow' : 'red'); ?>-100 border border-<?php echo $status === 'success' ? 'green' : ($status === 'warning' ? 'yellow' : 'red'); ?>-400 text-<?php echo $status === 'success' ? 'green' : ($status === 'warning' ? 'yellow' : 'red'); ?>-700 px-4 py-3 rounded mb-4"> <?php echo htmlspecialchars($message); ?> </div> <div class="text-center"> <a href="/" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Back to Home </a> </div> </div> </body> </html>
🛠️ Advanced Configuration
$khalti = new Khalti([ 'environment' => 'sandbox', 'secretKey' => 'your_secret_key', 'publicKey' => 'your_public_key', // Optional 'enableLogging' => true, 'logPath' => '/path/to/logs/khalti.log', 'logLevel' => 'info', // debug, info, warning, error, critical 'timeout' => 30 ]);
📋 API Reference
Payment Initiation
$response = $khalti->ePayment()->initiate([ 'return_url' => 'https://yoursite.com/success', // Required 'website_url' => 'https://yoursite.com', // Required 'amount' => 1000, // Required (in paisa) 'purchase_order_id' => 'ORDER-123', // Required 'purchase_order_name' => 'Product Name', // Required 'customer_info' => [ // Optional 'name' => 'John Doe', 'email' => 'john@example.com', 'phone' => '9800000000' ], 'amount_breakdown' => [ // Optional ['label' => 'Product', 'amount' => 900], ['label' => 'VAT', 'amount' => 100] ], 'product_details' => [ // Optional [ 'identity' => 'PROD-001', 'name' => 'Product Name', 'total_price' => 1000, 'quantity' => 1, 'unit_price' => 1000 ] ] ]);
Payment Verification
$result = $khalti->ePayment()->verify($pidx); // Response: // [ // 'pidx' => 'payment_id', // 'total_amount' => 1000, // 'status' => 'Completed', // Completed, Pending, User canceled, Expired, Refunded // 'transaction_id' => 'transaction_id', // 'fee' => 0, // 'refunded' => false // ]
🚨 Error Handling
use KhaltiSDK\Exceptions\ValidationException; use KhaltiSDK\Exceptions\ApiException; use KhaltiSDK\Exceptions\NetworkException; use KhaltiSDK\Exceptions\ConfigurationException; try { $response = $khalti->ePayment()->initiate($params); } catch (ValidationException $e) { // Invalid parameters echo "Validation Error: " . $e->getMessage(); } catch (ApiException $e) { // API error echo "API Error: " . $e->getMessage(); } catch (NetworkException $e) { // Network error echo "Network Error: " . $e->getMessage(); } catch (ConfigurationException $e) { // Configuration error echo "Configuration Error: " . $e->getMessage(); }
📦 Requirements
- PHP 7.2 or higher
- cURL extension
- JSON extension
📄 License
MIT License - see LICENSE file for details.
🆘 Support
- Documentation: Khalti API Docs
- Sandbox: test-admin.khalti.com
- Production: admin.khalti.com
- Issues: GitHub Issues
🔄 Changelog
v1.1.1
- Enhanced validation and error handling
- Improved documentation
- Added comprehensive examples
- Fixed API endpoint compatibility
v1.1.0
- Initial release with Web Checkout (KPG-2) support
- Payment initiation and verification
- Comprehensive error handling
- Logging support