feat(notifications): implement comprehensive telegram notifications for payment providers
- Add NotifyMe trait with centralized Telegram bot integration - Implement webhook notifications for Polar, OxaPay, and ActivationKey providers - Add subscription lifecycle notifications (create, activate, cancel, pause, resume) - Enhance Polar webhook processing with user context and error handling - Fix subscription.updated and subscription.canceled webhook column errors - Add idempotent webhook processing to prevent duplicate handling
This commit is contained in:
@@ -7,6 +7,7 @@ use App\Models\ActivationKey;
|
||||
use App\Models\Plan;
|
||||
use App\Models\Subscription;
|
||||
use App\Models\User;
|
||||
use App\NotifyMe;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -14,6 +15,8 @@ use Illuminate\Support\Str;
|
||||
|
||||
class ActivationKeyProvider implements PaymentProviderContract
|
||||
{
|
||||
use NotifyMe;
|
||||
|
||||
protected array $config;
|
||||
|
||||
public function __construct(array $config = [])
|
||||
@@ -74,6 +77,9 @@ class ActivationKeyProvider implements PaymentProviderContract
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Notify activation key generated
|
||||
$this->notifyActivationKeyGenerated($user, $plan, $activationKey);
|
||||
|
||||
return [
|
||||
'provider_subscription_id' => $keyRecord->id,
|
||||
'status' => 'pending_activation',
|
||||
@@ -106,6 +112,9 @@ class ActivationKeyProvider implements PaymentProviderContract
|
||||
'cancellation_reason' => $reason,
|
||||
]);
|
||||
|
||||
// Notify subscription cancelled
|
||||
$this->notifySubscriptionCancelled($subscription, $reason ?: 'Manual cancellation');
|
||||
|
||||
return true;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
@@ -381,6 +390,10 @@ class ActivationKeyProvider implements PaymentProviderContract
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Notify activation key redeemed and subscription activated
|
||||
$this->notifyActivationKeyRedeemed($user, $plan, $activationKey);
|
||||
$this->notifySubscriptionActivated($user, $plan, $subscription);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'subscription_id' => $subscription->id,
|
||||
@@ -494,4 +507,79 @@ class ActivationKeyProvider implements PaymentProviderContract
|
||||
{
|
||||
throw new \Exception('Import to activation keys not implemented');
|
||||
}
|
||||
|
||||
// Notification methods
|
||||
protected function notifyActivationKeyGenerated(User $user, Plan $plan, string $activationKey): void
|
||||
{
|
||||
$message = "🔑 ACTIVATION KEY GENERATED\n".
|
||||
"👤 User: {$user->name} ({$user->email})\n".
|
||||
"📋 Plan: {$plan->name}\n".
|
||||
'💰 Price: $'.number_format($plan->price, 2)."\n".
|
||||
"🏪 Provider: Activation Key\n".
|
||||
"🔑 Key: {$activationKey}\n".
|
||||
'📅 Generated: '.now()->format('Y-m-d H:i:s');
|
||||
|
||||
$this->sendTelegramNotification($message);
|
||||
}
|
||||
|
||||
protected function notifyActivationKeyRedeemed(User $user, Plan $plan, string $activationKey): void
|
||||
{
|
||||
$message = "✅ ACTIVATION KEY REDEEMED\n".
|
||||
"👤 User: {$user->name} ({$user->email})\n".
|
||||
"📋 Plan: {$plan->name}\n".
|
||||
"🏪 Provider: Activation Key\n".
|
||||
"🔑 Key: {$activationKey}\n".
|
||||
'📅 Redeemed: '.now()->format('Y-m-d H:i:s');
|
||||
|
||||
$this->sendTelegramNotification($message);
|
||||
}
|
||||
|
||||
protected function notifySubscriptionActivated(User $user, Plan $plan, Subscription $subscription): void
|
||||
{
|
||||
$message = "🎉 SUBSCRIPTION ACTIVATED\n".
|
||||
"👤 User: {$user->name} ({$user->email})\n".
|
||||
"📋 Plan: {$plan->name}\n".
|
||||
"🏪 Provider: Activation Key\n".
|
||||
"🔄 Subscription ID: {$subscription->id}\n".
|
||||
'📅 Activated: '.now()->format('Y-m-d H:i:s');
|
||||
|
||||
$this->sendTelegramNotification($message);
|
||||
}
|
||||
|
||||
protected function notifyProviderError(string $operation, string $error, array $context = []): void
|
||||
{
|
||||
$contextStr = '';
|
||||
if (! empty($context)) {
|
||||
$contextStr = '📝 Details: '.json_encode(array_slice($context, 0, 3, true), JSON_UNESCAPED_SLASHES)."\n";
|
||||
if (count($context) > 3) {
|
||||
$contextStr .= '📝 Additional: '.(count($context) - 3).' more items'."\n";
|
||||
}
|
||||
}
|
||||
|
||||
$message = "🚨 PROVIDER ERROR\n".
|
||||
"🏪 Provider: Activation Key\n".
|
||||
"📡 Operation: {$operation}\n".
|
||||
"💥 Error: {$error}\n".
|
||||
$contextStr.
|
||||
'⏰ Time: '.now()->format('Y-m-d H:i:s');
|
||||
|
||||
$this->sendTelegramNotification($message);
|
||||
}
|
||||
|
||||
protected function notifySubscriptionCancelled(Subscription $subscription, string $reason): void
|
||||
{
|
||||
$user = $subscription->user;
|
||||
$plan = $subscription->plan;
|
||||
|
||||
$message = "❌ SUBSCRIPTION CANCELLED\n".
|
||||
"👤 User: {$user->name} ({$user->email})\n".
|
||||
"📋 Plan: {$plan->name}\n".
|
||||
"🏪 Provider: Activation Key\n".
|
||||
"💭 Reason: {$reason}\n".
|
||||
"🆔 Subscription ID: {$subscription->id}\n".
|
||||
($subscription->ends_at ? '📅 Effective: '.$subscription->ends_at->format('Y-m-d')."\n" : '').
|
||||
'⏰ Cancelled: '.now()->format('Y-m-d H:i:s');
|
||||
|
||||
$this->sendTelegramNotification($message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user