kkxdev/laravel-phonepe-autopay
Composer 安装命令:
composer require kkxdev/laravel-phonepe-autopay
包简介
Production-grade PhonePe Payment Gateway SDK for Laravel with AutoPay (Recurring Payments) support
README 文档
README
Production-grade PhonePe Payment Gateway SDK for Laravel with full AutoPay (Recurring Payments) support. Built with enterprise resilience patterns, comprehensive error handling, and complete test coverage.
Version 1.0.0 - Initial stable release with full PhonePe AutoPay API coverage
✨ Features
- ✅ Complete API Coverage - All PhonePe AutoPay endpoints implemented
- ✅ OAuth Token Management - Automatic token caching and refresh
- ✅ Subscription Lifecycle - Setup, status, pause, unpause, cancel, revoke
- ✅ Recurring Redemption - Notify, execute, and track recurring payments
- ✅ Refund Management - Create and track refunds
- ✅ Webhook Verification - SHA256 signature validation
- ✅ Enterprise Resilience - Retry policy with exponential backoff
- ✅ Circuit Breaker - Protection against cascading failures
- ✅ Immutable DTOs - Type-safe request/response objects with validation
- ✅ PSR-3 Logging - Comprehensive logging throughout
- ✅ Laravel 8.x | 9.x | 10.x | 11.x | 12.x - Compatible with modern Laravel versions
- ✅ PHP 8.0+ - Modern PHP with strict types
📦 Installation
Install via Composer:
composer require kkxdev/laravel-phonepe-autopay
Publish the configuration file:
php artisan vendor:publish --tag=phonepe-config
⚙️ Configuration
Add your PhonePe credentials to .env:
# Environment: sandbox or production PHONEPE_ENV=sandbox # Credentials (get from PhonePe Dashboard) PHONEPE_MERCHANT_ID=your_merchant_id PHONEPE_CLIENT_ID=your_client_id PHONEPE_CLIENT_SECRET=your_client_secret PHONEPE_CLIENT_VERSION=v1 # Redirect URLs PHONEPE_SUCCESS_URL=https://yourdomain.com/payment/success PHONEPE_FAILURE_URL=https://yourdomain.com/payment/failure # Webhook Configuration PHONEPE_WEBHOOK_USERNAME=your_webhook_username PHONEPE_WEBHOOK_PASSWORD=your_webhook_password # Optional: Resilience Settings PHONEPE_RETRY_ENABLED=true PHONEPE_RETRY_MAX_ATTEMPTS=3 PHONEPE_CIRCUIT_BREAKER_ENABLED=true PHONEPE_CIRCUIT_BREAKER_THRESHOLD=5 # Optional: Logging PHONEPE_LOGGING=true PHONEPE_DEBUG=false
🚀 Usage
Setup Subscription
use Kkxdev\PhonePe\Facades\PhonePe; use Kkxdev\PhonePe\DTO\Subscription\SubscriptionSetupRequest; $request = SubscriptionSetupRequest::fromArray([ 'merchantOrderId' => 'ORDER_' . time(), 'amount' => 100000, // Amount in paisa (1000 INR) 'merchantSubscriptionId' => 'SUB_' . time(), 'subscriptionType' => 'RECURRING', 'authWorkflowType' => 'TRANSACTION', 'amountType' => 'FIXED', 'maxAmount' => 100000, 'frequency' => 'MONTHLY', // DAILY, WEEKLY, MONTHLY, QUARTERLY, HALFYEARLY, YEARLY 'productType' => 'UPI_MANDATE', 'redirectUrl' => 'https://yourdomain.com/payment/success', 'cancelRedirectUrl' => 'https://yourdomain.com/payment/cancel', 'message' => 'Monthly subscription payment', 'metaInfo' => [ 'udf1' => 'custom_data_1', 'udf2' => 'custom_data_2', ], ]); try { $response = PhonePe::subscription()->setup($request); // Redirect user to PhonePe authorization page return redirect($response['redirectUrl']); } catch (\Kkxdev\PhonePe\Exceptions\ValidationException $e) { // Handle validation errors $errors = $e->getErrors(); } catch (\Kkxdev\PhonePe\Exceptions\ApiException $e) { // Handle API errors $statusCode = $e->getStatusCode(); $responseBody = $e->getResponseBody(); }
Check Subscription Status
use Kkxdev\PhonePe\Facades\PhonePe; $status = PhonePe::subscription()->getStatus('SUB_123456'); if ($status->isActive()) { // Subscription is active echo "Subscription ID: {$status->subscriptionId}\n"; echo "State: {$status->state}\n"; echo "Frequency: {$status->frequency}\n"; echo "Max Amount: {$status->maxAmount}\n"; } elseif ($status->isCancelled()) { // Subscription was cancelled/revoked } elseif ($status->isPaused()) { // Subscription is paused }
Check Order Status
use Kkxdev\PhonePe\Facades\PhonePe; $orderStatus = PhonePe::subscription()->getOrderStatus('ORDER_123456'); if ($orderStatus->isCompleted()) { // Payment completed successfully $transactionId = $orderStatus->paymentDetails[0]['transactionId'] ?? null; } elseif ($orderStatus->isFailed()) { // Payment failed } elseif ($orderStatus->isPending()) { // Payment still pending }
Notify Redemption (Recurring Payment)
Important: Must be called 24 hours before executing redemption.
use Kkxdev\PhonePe\Facades\PhonePe; use Kkxdev\PhonePe\DTO\Redemption\RedemptionNotifyRequest; $request = RedemptionNotifyRequest::fromArray([ 'merchantOrderId' => 'REDEMPTION_' . time(), 'amount' => 100000, // Amount in paisa 'merchantSubscriptionId' => 'SUB_123456', 'redemptionRetryStrategy' => 'STANDARD', // STANDARD or CUSTOM ]); $response = PhonePe::redemption()->notify($request); // Store orderId for later execution $orderId = $response['orderId']; $state = $response['state']; // NOTIFIED
Execute Redemption (Charge Customer)
Important: Call this after 24-hour notification period.
use Kkxdev\PhonePe\Facades\PhonePe; use Kkxdev\PhonePe\DTO\Redemption\RedemptionExecuteRequest; $request = RedemptionExecuteRequest::fromArray([ 'merchantOrderId' => 'REDEMPTION_123456', 'idempotencyKey' => 'IDEMPOTENT_KEY_' . time(), // Optional but recommended ]); $response = PhonePe::redemption()->execute($request); if ($response['state'] === 'COMPLETED') { $transactionId = $response['transactionId']; // Payment successful } elseif ($response['state'] === 'FAILED') { // Payment failed }
Check Redemption Status
use Kkxdev\PhonePe\Facades\PhonePe; $status = PhonePe::redemption()->getStatus('REDEMPTION_123456'); if ($status->isCompleted()) { echo "Transaction ID: {$status->transactionId}\n"; } elseif ($status->isFailed()) { echo "Error Code: {$status->errorCode}\n"; }
Cancel Subscription
use Kkxdev\PhonePe\Facades\PhonePe; PhonePe::subscription()->cancel('SUB_123456'); // Returns void on success (204 No Content)
Create Refund
use Kkxdev\PhonePe\Facades\PhonePe; use Kkxdev\PhonePe\DTO\Refund\RefundRequest; $request = RefundRequest::fromArray([ 'merchantRefundId' => 'REFUND_' . time(), 'originalMerchantOrderId' => 'ORDER_123456', 'amount' => 50000, // Amount to refund in paisa ]); $response = PhonePe::refund()->create($request); $refundId = $response['refundId']; $state = $response['state']; // PENDING, CONFIRMED, COMPLETED, FAILED
Check Refund Status
use Kkxdev\PhonePe\Facades\PhonePe; $status = PhonePe::refund()->getStatus('REFUND_123456'); if ($status->isCompleted()) { echo "Refund completed successfully\n"; echo "Amount: {$status->amount}\n"; } elseif ($status->isFailed()) { echo "Refund failed: {$status->errorCode}\n"; }
🔔 Webhook Handling
PhonePe sends webhooks for subscription lifecycle events (pause, unpause, revoke).
Verify Webhook Signature
use Kkxdev\PhonePe\Facades\PhonePe; use Illuminate\Http\Request; public function handleWebhook(Request $request) { try { $authHeader = $request->header('Authorization'); $payload = $request->all(); // Verify and parse webhook $event = PhonePe::verifyWebhook($authHeader, $payload); // Handle different event types if ($event->isSubscriptionPaused()) { $subscriptionId = $event->getMerchantSubscriptionId(); // Handle pause event } elseif ($event->isSubscriptionUnpaused()) { $subscriptionId = $event->getMerchantSubscriptionId(); // Handle unpause event } elseif ($event->isSubscriptionRevoked()) { $subscriptionId = $event->getMerchantSubscriptionId(); // Handle revocation (user-initiated cancellation) } elseif ($event->isRedemptionCompleted()) { // Handle successful redemption } elseif ($event->isRedemptionFailed()) { // Handle failed redemption } return response()->json(['status' => 'success'], 200); } catch (\Kkxdev\PhonePe\Exceptions\WebhookVerificationException $e) { // Signature verification failed return response()->json(['error' => 'Invalid signature'], 403); } }
🔐 Security
Token Management
- OAuth tokens are automatically cached with TTL
- Tokens refresh 90 seconds before expiry
- Thread-safe caching via Laravel's cache system
Webhook Verification
- SHA256 signature validation
- Configurable username/password
- Protects against replay attacks
Idempotency
- Use idempotency keys for redemption execution
- Prevents duplicate charges
🛡️ Resilience
Retry Policy
Automatically retries failed requests with exponential backoff:
// Configured in config/phonepe.php 'retry' => [ 'enabled' => true, 'max_attempts' => 3, 'base_delay_ms' => 1000, 'max_delay_ms' => 10000, 'jitter' => true, // Prevents thundering herd ],
Retry Triggers:
- Network timeouts
- Connection failures
- 5xx server errors
Non-Retryable:
- 4xx client errors (validation, auth, etc.)
Circuit Breaker
Protects against cascading failures:
'circuit_breaker' => [ 'enabled' => true, 'failure_threshold' => 5, // Open after 5 consecutive failures 'success_threshold' => 2, // Close after 2 successes in half-open 'cooldown_seconds' => 60, // Wait 60s before testing recovery ],
States:
- CLOSED: Normal operation
- OPEN: Blocking requests (service is down)
- HALF_OPEN: Testing recovery
📊 Subscription Flow Diagram
┌─────────┐ ┌─────────┐
│ Merchant│ │ PhonePe │
└────┬────┘ └────┬────┘
│ │
│ 1. Setup Subscription │
│──────────────────────────────────────────>│
│ │
│ 2. Return redirectUrl │
│<──────────────────────────────────────────│
│ │
│ 3. User authorizes via PSP app │
│━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━>│
│ │
│ 4. Redirect back │
│<━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│
│ │
│ 5. Check Order Status │
│──────────────────────────────────────────>│
│ │
│ 6. Return COMPLETED │
│<──────────────────────────────────────────│
│ │
├──── Recurring Redemption Cycle ──────────┤
│ │
│ 7. Notify Redemption │
│──────────────────────────────────────────>│
│ │
│ Wait 24 hours │
│ │
│ 8. Execute Redemption │
│──────────────────────────────────────────>│
│ │
│ 9. Return COMPLETED + transactionId │
│<──────────────────────────────────────────│
│ │
└──── Repeat per frequency ────────────────┘
🧪 Testing
# Run tests composer test # Run tests with coverage composer test-coverage
Mock HTTP Responses
use Kkxdev\PhonePe\Contracts\HttpClientInterface; // In your tests $mockClient = Mockery::mock(HttpClientInterface::class); $mockClient->shouldReceive('send') ->andReturn([ 'orderId' => 'PG_ORDER_123', 'state' => 'PENDING', 'redirectUrl' => 'https://phonepe.com/...', ]); $this->app->instance(HttpClientInterface::class, $mockClient);
🏗️ Architecture
This package follows SOLID principles and enterprise design patterns:
- Adapter Pattern: HTTP client abstraction
- Strategy Pattern: Environment switching (sandbox/production)
- Factory Pattern: Versioned API clients
- DTO Pattern: Immutable request/response objects
- Retry Policy Pattern: Network resilience
- Circuit Breaker Pattern: Service protection
- Facade Pattern: Developer ergonomics
📘 API Reference
SubscriptionApiInterface
| Method | Description |
|---|---|
setup(SubscriptionSetupRequest) |
Create new subscription |
getOrderStatus(string) |
Check order status |
getStatus(string) |
Check subscription status |
cancel(string) |
Cancel active subscription |
RedemptionApiInterface
| Method | Description |
|---|---|
notify(RedemptionNotifyRequest) |
Notify upcoming charge (24h before) |
execute(RedemptionExecuteRequest) |
Execute recurring charge |
getStatus(string) |
Check redemption status |
RefundApiInterface
| Method | Description |
|---|---|
create(RefundRequest) |
Create refund |
getStatus(string) |
Check refund status |
🤝 Contributing
Contributions are welcome! Please ensure:
- Code follows PSR-12 standards
- All tests pass
- New features include tests
- Documentation is updated
📄 License
MIT License. See LICENSE for details.
🙏 Support
Built with ❤️ by KKXDev
kkxdev/laravel-phonepe-autopay 适用场景与选型建议
kkxdev/laravel-phonepe-autopay 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 22 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 26 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「payment」 「subscription」 「gateway」 「laravel」 「recurring」 「PhonePe」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 kkxdev/laravel-phonepe-autopay 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 kkxdev/laravel-phonepe-autopay 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 kkxdev/laravel-phonepe-autopay 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
repository php library
Payyo Gateway for the Omnipay payment processing library
MaxAl Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.
Rinvex Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.
Rinvex Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.
Rinvex Subscriptions is a flexible plans and subscription management system for Laravel, with the required tools to run your SAAS like services efficiently. It's simple architecture, accompanied by powerful underlying to afford solid platform for your business.
统计信息
- 总下载量: 22
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 4
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-02-26