File: /var/www/html/spion/app/Http/Controllers/PaymentsController.php
<?php
namespace App\Http\Controllers;
use App\Models\Plan;
use App\Models\UserSubscription;
use App\Models\UserTransaction;
use App\Models\UserWebsite;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Razorpay\Api\Api;
use Razorpay\Api\Errors\BadRequestError;
use Razorpay\Api\Errors\UnauthorizedError;
use Razorpay\Api\Errors\MethodNotAllowedError;
class PaymentsController extends Controller
{
public function buy_subscription_plan(Request $request)
{
$request->validate([
'plan_id' => 'required|string|exists:plans,key',
'website_id' => 'nullable|string',
]);
try {
// Fetch the plan details
$plan = Plan::where('key', $request->plan_id)->first();
if (!$plan) {
return response()->json(['error' => 'Invalid plan selected.'], 400);
}
// Razorpay credentials
$razorpayKeyId = env('RAZORPAY_KEY_ID');
$razorpayKeySecret = env('RAZORPAY_KEY_SECRET');
$api = new Api($razorpayKeyId, $razorpayKeySecret);
// Create a Razorpay subscription
try {
$subscription = $api->subscription->create([
'plan_id' => $request->plan_id,
'total_count' => 12, // You can adjust this value based on your requirements
'customer_notify' => 1,
'notes' => [
'plan_name' => $plan->name,
'website_id' => $request->website_id,
'user_id' => auth()->user()->id ?? null,
],
]);
if ($subscription) {
// Return the subscription URL as response
return response()->json(['subscription_url' => $subscription->short_url]);
}
} catch (BadRequestError $e) {
Log::error('Razorpay Subscription Error', ['message' => $e->getMessage()]);
} catch (\Exception $e) {
Log::error('General Razorpay Error', ['message' => $e->getMessage()]);
}
return response()->json(['error' => 'Unable to create subscription.'], 500);
} catch (\Exception $e) {
Log::error('Subscription Plan Error', ['message' => $e->getMessage()]);
return response()->json(['error' => 'Unable to process subscription. Please try again later.'], 500);
}
}
public function handleWebhook(Request $request)
{
$input = $request->all();
Log::info('Webhook Payload:--------' .json_encode($input));
// dd($input);
// return true;
if (!isset($input['event'])) {
Log::error('Event type not found in the payload');
return response()->json(['status' => 'error', 'message' => 'Event type missing'], 400);
}
$event = $input['event'];
// Handle events based on their type
switch ($event) {
case 'payment.authorized':
$this->handlePaymentAuthorized($input);
break;
case 'payment.failed':
$this->handlePaymentFailed($input);
break;
case 'payment.captured':
$this->handlePaymentCaptured($input);
break;
case 'payment.dispute.created':
$this->handlePaymentDisputeCreated($input);
break;
// case 'order.paid':
// $this->handleOrderPaid($input);
// break;
// case 'order.notification.delivered':
// $this->handleOrderNotificationDelivered($input);
// break;
// case 'order.notification.failed':
// $this->handleOrderNotificationFailed($input);
// break;
// case 'invoice.paid':
// $this->handleInvoicePaid($input);
// break;
// case 'invoice.partially_paid':
// $this->handleInvoicePartiallyPaid($input);
// break;
// case 'invoice.expired':
// $this->handleInvoiceExpired($input);
// break;
case 'subscription.authenticated':
$this->handleSubscriptionAuthenticated($input);
break;
case 'subscription.paused':
$this->handleSubscriptionPaused($input);
break;
case 'subscription.resumed':
$this->handleSubscriptionResumed($input);
break;
case 'subscription.activated':
$this->handleSubscriptionActivated($input);
break;
case 'subscription.pending':
$this->handleSubscriptionPending($input);
break;
case 'subscription.halted':
$this->handleSubscriptionHalted($input);
break;
case 'subscription.charged':
$this->handleSubscriptionCharged($input);
break;
case 'subscription.cancelled':
$this->handleSubscriptionCancelled($input);
break;
case 'subscription.completed':
$this->handleSubscriptionCompleted($input);
break;
case 'subscription.updated':
$this->handleSubscriptionUpdated($input);
break;
// case 'payment.dispute.won':
// $this->handlePaymentDisputeWon($input);
// break;
// case 'payment.dispute.lost':
// $this->handlePaymentDisputeLost($input);
// break;
// case 'payment.dispute.closed':
// $this->handlePaymentDisputeClosed($input);
// break;
// case 'payment.dispute.under_review':
// $this->handlePaymentDisputeUnderReview($input);
// break;
// case 'payment.dispute.action_required':
// $this->handlePaymentDisputeActionRequired($input);
// break;
// case 'payment.downtime.started':
// $this->handlePaymentDowntimeStarted($input);
// break;
// case 'payment.downtime.updated':
// $this->handlePaymentDowntimeUpdated($input);
// break;
// case 'payment.downtime.resolved':
// $this->handlePaymentDowntimeResolved($input);
// break;
default:
Log::warning("Unhandled event type: $event");
break;
}
// $statusMap = [
// 'created' => 1,
// 'authenticated' => 2,
// 'active' => 3,
// 'halted' => 4,
// 'cancelled' => 5,
// ];
// if (isset($input['payload']['subscription']['entity'])) {
// $subscription = $input['payload']['subscription']['entity'];
// // dd(Carbon::createFromTimestamp($subscription['charge_at'])->format('d-m-Y H:i:s'));
// $data = [
// 'user_id' => $subscription['notes']['user_id'] ?? null,
// 'website_id' => $subscription['notes']['website_id'] ?? null,
// 'plan_name' => $subscription['notes']['plan_name'] ?? null,
// 'rz_subscription_id' => $subscription['id'],
// 'rz_plan_id' => $subscription['plan_id'],
// 'customer_id' => $subscription['customer_id'],
// 'start_at' => $subscription['start_at'],
// 'end_at' => $subscription['end_at'],
// 'rz_quantity' => $subscription['quantity'],
// 'rz_status' => $statusMap[$subscription['status']] ?? null,
// 'charge_at' => $subscription['charge_at'],
// ];
// // dd($data);
// UserSubscription::updateOrCreate(
// ['rz_subscription_id' => $subscription['id']],
// $data
// );
// // Log success
// Log::info('Subscription data stored successfully', $data);
// } else {
// // Log error if subscription data is missing
// Log::error('Subscription entity not found in the payload');
// }
// Return a success response for the webhook
return response()->json(['status' => 'success']);
}
// Function to handle subscription update and save
protected function handleSubscriptionEvent($input, $status) {
if (isset($input['payload']['subscription']['entity'])) {
$subscription = $input['payload']['subscription']['entity'];
$statusMap = [
'created' => 1, // Pending
'authenticated' => 2, // Authenticated
'active' => 3, // Active
'halted' => 4, // Halted
'cancelled' => 5, // Cancelled
'paused' => 6, // Paused
'resumed' => 7, // Resumed
'charged' => 8, // Charged
'completed' => 9, // Completed
'updated' => 10, // Updated
// 'expired' => 11, // Expired
// 'failed' => 12,
];
// Mapping status using the provided $status
$statusValue = $statusMap[$status] ?? null;
$data = [
'user_id' => $subscription['notes']['user_id'] ?? null,
'website_id' => $subscription['notes']['website_id'] ?? null,
'plan_name' => $subscription['notes']['plan_name'] ?? null,
'rz_subscription_id' => $subscription['id'],
'rz_plan_id' => $subscription['plan_id'],
'customer_id' => $subscription['customer_id'],
'start_at' => $subscription['start_at'],
'end_at' => $subscription['end_at'],
'rz_quantity' => $subscription['quantity'],
'rz_status' => $statusValue,
'charge_at' => $subscription['charge_at'],
];
// Save the subscription data to the database
UserSubscription::updateOrCreate(
['rz_subscription_id' => $subscription['id']],
$data
);
// Add specific logic for payment details
$payment = $input['payload']['payment']['entity'] ?? null;
// dd($payment);
if ($payment) {
Log::info('Payment details received', $payment);
// Update the subscription record in the payment transaction
$transaction = UserTransaction::where('transaction_id', $payment['id'])->first();
if ($transaction) {
$transaction->update(['rz_subscription_id' => $input['payload']['subscription']['entity']['id']]);
Log::info('Transaction updated with subscription ID');
}
}
$websiteId = $subscription['notes']['website_id'] ?? null;
if ($websiteId) {
Log::info('website ID details received', ['id' => $websiteId]);
// Find the UserWebsite record associated with the website_id
$userWebsite = UserWebsite::where('id', $websiteId)->first();
if ($userWebsite) {
// Update the status to 2
$userWebsite->update(['status' => 2]);
Log::info('UserWebsite status updated to 2', ['id' => $websiteId]);
} else {
Log::warning('No UserWebsite found for the given website ID', ['id' => $websiteId]);
}
}
// Log success
Log::info('Subscription data stored successfully', $data);
} else {
// Log error if subscription data is missing
Log::error('Subscription entity not found in the payload');
}
}
protected function handlePaymentAuthorized($input)
{
$payment = $input['payload']['payment']['entity'] ?? null;
if ($payment) {
$paymentId = $payment['id'];
$customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
// Set the numeric status for 'payment.authorized' event
$paymentStatus = 1; // Assuming 'authorized' means pending
Log::info('Payment Authorized', $payment);
// Update or create the transaction record with the 'pending' status (1)
UserTransaction::updateOrCreate(
['transaction_id' => $paymentId], // Check if the transaction already exists
[
'transaction_id' => $paymentId,
'customer_id' => $customerId,
'pay_status' => $paymentStatus,
]
);
}
}
protected function handlePaymentFailed($input)
{
$payment = $input['payload']['payment']['entity'] ?? null;
if ($payment) {
$paymentId = $payment['id'];
$customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
// Set the numeric status for 'payment.failed' event
$paymentStatus = 4; // 'failed' corresponds to status 4
Log::info('Payment Failed', $payment);
// Update or create the transaction record with the 'failed' status (4)
UserTransaction::updateOrCreate(
['transaction_id' => $paymentId], // Check if the transaction already exists
[
'transaction_id' => $paymentId,
'customer_id' => $customerId,
'pay_status' => $paymentStatus,
]
);
}
}
protected function handlePaymentCaptured($input)
{
$payment = $input['payload']['payment']['entity'] ?? null;
if ($payment) {
$paymentId = $payment['id'];
$customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
// Set the numeric status for 'payment.captured' event
$paymentStatus = 3; // 'captured' corresponds to status 3
Log::info('Payment Captured', $payment);
// Update or create the transaction record with the 'paid' status (3)
UserTransaction::updateOrCreate(
['transaction_id' => $paymentId], // Check if the transaction already exists
[
'transaction_id' => $paymentId,
'customer_id' => $customerId,
'pay_status' => $paymentStatus,
]
);
}
}
protected function handlePaymentDisputeCreated($input)
{
$dispute = $input['payload']['dispute']['entity'] ?? null;
if ($dispute) {
$disputeId = $dispute['id'];
$paymentId = $dispute['payment_id'];
// Set the numeric status for 'payment.dispute.created' event
$paymentStatus = 4; // Dispute status might map to halted (4)
Log::info('Payment Dispute Created', $dispute);
// Update or create the transaction record with the 'halted' status (4)
UserTransaction::updateOrCreate(
['transaction_id' => $paymentId], // Check if the transaction already exists
[
'transaction_id' => $paymentId,
'pay_status' => $paymentStatus,
]
);
}
}
// protected function handleOrderPaid($input)
// {
// $order = $input['payload']['order']['entity'] ?? null;
// if ($order) {
// Log::info('Order Paid', $order);
// // Add your logic here
// }
// }
// protected function handleOrderNotificationDelivered($input)
// {
// $notification = $input['payload']['order']['entity'] ?? null;
// if ($notification) {
// Log::info('Order Notification Delivered', $notification);
// // Add your logic here
// }
// }
// protected function handleOrderNotificationFailed($input)
// {
// $notification = $input['payload']['order']['entity'] ?? null;
// if ($notification) {
// Log::info('Order Notification Failed', $notification);
// // Add your logic here
// }
// }
// protected function handleInvoicePaid($input)
// {
// $invoice = $input['payload']['invoice']['entity'] ?? null;
// if ($invoice) {
// Log::info('Invoice Paid', $invoice);
// // Add your logic here
// }
// }
// protected function handleInvoicePartiallyPaid($input)
// {
// $invoice = $input['payload']['invoice']['entity'] ?? null;
// if ($invoice) {
// Log::info('Invoice Partially Paid', $invoice);
// // Add your logic here
// }
// }
// protected function handleInvoiceExpired($input)
// {
// $invoice = $input['payload']['invoice']['entity'] ?? null;
// if ($invoice) {
// Log::info('Invoice Expired', $invoice);
// // Add your logic here
// }
// }
// Handle subscription events
protected function handleSubscriptionAuthenticated($input)
{
Log::info('Subscription Authenticated');
$this->handleSubscriptionEvent($input, 'authenticated');
}
protected function handleSubscriptionPaused($input)
{
Log::info('Subscription Paused');
$this->handleSubscriptionEvent($input, 'paused');
}
protected function handleSubscriptionResumed($input)
{
Log::info('Subscription Resumed');
$this->handleSubscriptionEvent($input, 'resumed');
}
protected function handleSubscriptionActivated($input)
{
Log::info('Subscription Activated');
$this->handleSubscriptionEvent($input, 'active');
}
protected function handleSubscriptionPending($input)
{
Log::info('Subscription Pending');
$this->handleSubscriptionEvent($input, 'created');
}
protected function handleSubscriptionHalted($input)
{
Log::info('Subscription Halted');
$this->handleSubscriptionEvent($input, 'halted');
}
protected function handleSubscriptionCharged($input)
{
Log::info('Subscription Charged');
$this->handleSubscriptionEvent($input, 'charged');
}
protected function handleSubscriptionCancelled($input)
{
$subscription = $input['payload']['subscription']['entity'] ?? null;
if ($subscription) {
Log::info('Subscription Cancelled', $subscription);
$this->handleSubscriptionEvent($input, 'cancelled');
// Add your logic here
}
}
protected function handleSubscriptionCompleted($input)
{
$subscription = $input['payload']['subscription']['entity'] ?? null;
if ($subscription) {
Log::info('Subscription Completed', $subscription);
$this->handleSubscriptionEvent($input, 'completed');
// Add your logic here
}
}
protected function handleSubscriptionUpdated($input)
{
$subscription = $input['payload']['subscription']['entity'] ?? null;
if ($subscription) {
Log::info('Subscription Updated', $subscription);
$this->handleSubscriptionEvent($input, 'updated');
// Add your logic here
}
}
// protected function handlePaymentDisputeWon($input)
// {
// $dispute = $input['payload']['dispute']['entity'] ?? null;
// if ($dispute) {
// Log::info('Payment Dispute Won', $dispute);
// // Add your logic here
// }
// }
// protected function handlePaymentDisputeLost($input)
// {
// $dispute = $input['payload']['dispute']['entity'] ?? null;
// if ($dispute) {
// Log::info('Payment Dispute Lost', $dispute);
// // Add your logic here
// }
// }
// protected function handlePaymentDisputeClosed($input)
// {
// $dispute = $input['payload']['dispute']['entity'] ?? null;
// if ($dispute) {
// Log::info('Payment Dispute Closed', $dispute);
// // Add your logic here
// }
// }
// protected function handlePaymentDisputeUnderReview($input)
// {
// $dispute = $input['payload']['dispute']['entity'] ?? null;
// if ($dispute) {
// Log::info('Payment Dispute Under Review', $dispute);
// // Add your logic here
// }
// }
// protected function handlePaymentDisputeActionRequired($input)
// {
// $dispute = $input['payload']['dispute']['entity'] ?? null;
// if ($dispute) {
// Log::info('Payment Dispute Action Required', $dispute);
// // Add your logic here
// }
// }
// protected function handlePaymentDowntimeStarted($input)
// {
// $downtime = $input['payload']['downtime']['entity'] ?? null;
// if ($downtime) {
// Log::info('Payment Downtime Started', $downtime);
// // Add your logic here
// }
// }
// protected function handlePaymentDowntimeUpdated($input)
// {
// $downtime = $input['payload']['downtime']['entity'] ?? null;
// if ($downtime) {
// Log::info('Payment Downtime Updated', $downtime);
// // Add your logic here
// }
// }
// protected function handlePaymentDowntimeResolved($input)
// {
// $downtime = $input['payload']['downtime']['entity'] ?? null;
// if ($downtime) {
// Log::info('Payment Downtime Resolved', $downtime);
// // Add your logic here
// }
// }
public function checkSubscriptionStatus(Request $request)
{
$websiteId = $request->website_id;
$planId = $request->plan_id;
$subscription = UserSubscription::where('website_id', $websiteId)->where('rz_plan_id', $planId)->latest()->first();
if ($subscription) {
if (in_array($subscription->rz_status, [2, 3, 8])) {
return response()->json(['status' => 'success']);
}
}
return response()->json(['status' => 'failed']);
}
public function subscription_transactions(Request $request)
{
$limit = 10; // Items per page
$currentPage = $request->page ?: 1; // Current page
$searchTerm = $request->search; // Get the search term from the request
$query = UserSubscription::with(['website', 'plan', 'transactions'])
->where('user_id', auth()->id());
// Apply search filter
if ($searchTerm) {
$query->whereHas('website', function ($query) use ($searchTerm) {
$query->where('first_name', 'like', '%' . $searchTerm . '%')
->orWhere('last_name', 'like', '%' . $searchTerm . '%')
->orWhere(DB::raw("CONCAT(first_name, ' ', last_name)"), 'like', '%' . $searchTerm . '%');
})->orWhereHas('plan', function ($query) use ($searchTerm) {
$query->where('name', 'like', '%' . $searchTerm . '%')
->orWhere('price', 'like', '%' . $searchTerm . '%');
})
->orWhereHas('transactions', function ($query) use ($searchTerm) {
$query->where('transaction_id', 'like', '%' . $searchTerm . '%');
});
}
// Paginate results
$totalSubscriptions = $query->count();
$subscriptions = $query
->skip(($currentPage - 1) * $limit)
->take($limit)
->get();
foreach ($subscriptions as $subscription) {
$subscription->formatted_start_at = Carbon::parse($subscription->start_at)->format('d-m-Y H:i:s');
}
$lastPage = ceil($totalSubscriptions / $limit); // Total pages
if ($request->ajax()) {
return response()->json([
'subscriptions' => $subscriptions,
'current_page' => $currentPage,
'last_page' => $lastPage,
]);
}
return view('user.transactions', compact('subscriptions'));
}
public function unsubscribe(Request $request)
{
$user = auth()->user();
// Find the subscription to be unsubscribed
$subscription = UserSubscription::where('user_id', $user->id)
->where('website_id', $request->website_id)
->first();
// dd($request->website_id);
if ($subscription) {
// Update the status to 'inactive' or delete the subscription
// $subscription->update(['rz_status' => '6']);
$subscription->delete();
$websiteId = $request->website_id;
if ($websiteId) {
$userWebsite = UserWebsite::where('id', $websiteId)->first();
if ($userWebsite) {
// Update the status to 1
$userWebsite->update(['status' => 1]);
Log::info('UserWebsite status updated to 1', ['id' => $websiteId]);
} else {
Log::warning('No UserWebsite found for the given website ID', ['id' => $websiteId]);
}
}
return response()->json(['status' => 'success', 'message' => 'Subscription successfully removed']);
}
return response()->json(['status' => 'failure', 'message' => 'Subscription not found']);
}
}