238 lines
9.0 KiB
PHP
238 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Plan;
|
|
use App\Models\User;
|
|
use App\Models\PaymentSetting;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Cashfree\Cashfree;
|
|
use Cashfree\Model\CreateOrderRequest;
|
|
use Cashfree\Model\CustomerDetails;
|
|
use Cashfree\Model\OrderMeta;
|
|
use Cashfree\Api\OrdersApi;
|
|
|
|
class CashfreeController extends Controller
|
|
{
|
|
/**
|
|
* Get Cashfree API credentials and configuration
|
|
*
|
|
* @return array
|
|
*/
|
|
private function getCashfreeCredentials()
|
|
{
|
|
$settings = getPaymentGatewaySettings();
|
|
|
|
$mode = $settings['payment_settings']['cashfree_mode'] ?? 'sandbox';
|
|
$baseUrl = $mode === 'production'
|
|
? 'https://api.cashfree.com/pg'
|
|
: 'https://sandbox.cashfree.com/pg';
|
|
|
|
return [
|
|
'app_id' => $settings['payment_settings']['cashfree_public_key'] ?? null,
|
|
'secret_key' => $settings['payment_settings']['cashfree_secret_key'] ?? null,
|
|
'mode' => $mode,
|
|
'base_url' => $baseUrl,
|
|
'currency' => $settings['general_settings']['defaultCurrency'] ?? 'INR'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Create a Cashfree payment session
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function createPaymentSession(Request $request)
|
|
{
|
|
$validated = validatePaymentRequest($request);
|
|
|
|
try {
|
|
$plan = Plan::findOrFail($validated['plan_id']);
|
|
$pricing = calculatePlanPricing($plan, $validated['coupon_code'] ?? null);
|
|
|
|
// Get Cashfree credentials
|
|
$credentials = $this->getCashfreeCredentials();
|
|
|
|
if (!$credentials['app_id'] || !$credentials['secret_key']) {
|
|
throw new \Exception(__('Cashfree API credentials not found'));
|
|
}
|
|
$orderId = 'plan_' . $plan->id . '_' . time() . '_' . uniqid();
|
|
|
|
// Configure Cashfree SDK
|
|
$cashfree = new Cashfree(
|
|
$credentials['mode'] === 'production' ? 1 : 0,
|
|
$credentials['app_id'],
|
|
$credentials['secret_key'],
|
|
'',
|
|
'',
|
|
'',
|
|
false
|
|
);
|
|
|
|
// Create customer details
|
|
$customerDetails = new CustomerDetails();
|
|
$customerDetails->setCustomerId('user_' . auth()->id());
|
|
$customerDetails->setCustomerName(auth()->user()->name ?? 'Customer');
|
|
$customerDetails->setCustomerEmail(auth()->user()->email ?? 'customer@example.com');
|
|
$customerDetails->setCustomerPhone(auth()->user()->phone ?? '9999999999');
|
|
|
|
// Create order meta
|
|
$orderMeta = new OrderMeta();
|
|
$orderMeta->setReturnUrl(route('dashboard'));
|
|
$orderMeta->setNotifyUrl(route('cashfree.webhook'));
|
|
|
|
// Create order request
|
|
$orderRequest = new CreateOrderRequest();
|
|
$orderRequest->setOrderId($orderId);
|
|
$orderRequest->setOrderAmount($pricing['final_price']);
|
|
$orderRequest->setOrderCurrency($credentials['currency']);
|
|
$orderRequest->setCustomerDetails($customerDetails);
|
|
$orderRequest->setOrderMeta($orderMeta);
|
|
$orderRequest->setOrderNote('Plan Subscription - ' . $plan->name);
|
|
$orderRequest->setOrderTags([
|
|
'plan_id' => (string)$plan->id,
|
|
'billing_cycle' => $request->billing_cycle,
|
|
'user_id' => (string)auth()->id()
|
|
]);
|
|
|
|
$apiResponse = $cashfree->PGCreateOrder($orderRequest);
|
|
|
|
return response()->json([
|
|
'payment_session_id' => $apiResponse[0]->getPaymentSessionId(),
|
|
'order_id' => $orderId,
|
|
'amount' => $pricing['final_price'],
|
|
'currency' => $credentials['currency'],
|
|
'mode' => $credentials['mode']
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => __('Failed to create payment session: ') . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify Cashfree payment
|
|
*
|
|
* @param \Illuminate\\Http\\Request $request
|
|
* @return \Illuminate\\Http\\JsonResponse
|
|
*/
|
|
public function verifyPayment(Request $request)
|
|
{
|
|
$validated = validatePaymentRequest($request, [
|
|
'order_id' => 'required|string',
|
|
'cf_payment_id' => 'nullable|string'
|
|
]);
|
|
|
|
try {
|
|
$credentials = $this->getCashfreeCredentials();
|
|
|
|
if (!$credentials['app_id'] || !$credentials['secret_key']) {
|
|
throw new \Exception(__('Cashfree API credentials not found'));
|
|
}
|
|
|
|
// Configure Cashfree SDK
|
|
$cashfree = new Cashfree(
|
|
$credentials['mode'] === 'production' ? 1 : 0,
|
|
$credentials['app_id'],
|
|
$credentials['secret_key'],
|
|
'',
|
|
'',
|
|
'',
|
|
false
|
|
);
|
|
$orderResponse = $cashfree->PGFetchOrder($validated['order_id']);
|
|
|
|
if ($orderResponse[0]->getOrderStatus() !== 'PAID') {
|
|
throw new \Exception(__('Payment not completed successfully'));
|
|
}
|
|
|
|
// Get payment details - response is array with payment objects
|
|
$paymentsResponse = $cashfree->PGOrderFetchPayments($validated['order_id']);
|
|
// Response structure: [payments_array, status_code, headers]
|
|
if (is_array($paymentsResponse) && isset($paymentsResponse[0]) && is_array($paymentsResponse[0])) {
|
|
$payments = $paymentsResponse[0]; // Direct array of payment objects
|
|
} else {
|
|
throw new \Exception(__('Invalid payment response structure'));
|
|
}
|
|
|
|
$successfulPayment = null;
|
|
foreach ($payments as $payment) {
|
|
// Payment is already an object from the SDK
|
|
if ($payment->getPaymentStatus() === 'SUCCESS') {
|
|
$successfulPayment = $payment;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$successfulPayment) {
|
|
throw new \Exception(__('No successful payment found for this order'));
|
|
}
|
|
|
|
$paymentData = [
|
|
'user_id' => auth()->id(),
|
|
'plan_id' => $validated['plan_id'],
|
|
'billing_cycle' => $validated['billing_cycle'],
|
|
'payment_method' => 'cashfree',
|
|
'coupon_code' => $validated['coupon_code'] ?? null,
|
|
'payment_id' => $successfulPayment->getCfPaymentId(),
|
|
];
|
|
|
|
$planOrder = processPaymentSuccess($paymentData);
|
|
|
|
return response()->json(['success' => true]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => __('Payment verification failed: ') . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle Cashfree webhook
|
|
*
|
|
* @param \Illuminate\\Http\\Request $request
|
|
* @return \Illuminate\\Http\\JsonResponse
|
|
*/
|
|
public function webhook(Request $request)
|
|
{
|
|
try {
|
|
$credentials = $this->getCashfreeCredentials();
|
|
|
|
// Verify webhook signature
|
|
$signature = $request->header('x-webhook-signature');
|
|
$timestamp = $request->header('x-webhook-timestamp');
|
|
$rawBody = $request->getContent();
|
|
|
|
$expectedSignature = base64_encode(hash_hmac('sha256', $timestamp . $rawBody, $credentials['secret_key'], true));
|
|
|
|
if (!hash_equals($expectedSignature, $signature)) {
|
|
return response()->json(['error' => 'Invalid signature'], 400);
|
|
}
|
|
|
|
$data = $request->json()->all();
|
|
|
|
if ($data['type'] === 'PAYMENT_SUCCESS_WEBHOOK') {
|
|
$paymentData = $data['data'];
|
|
|
|
// Extract plan and user info from order tags
|
|
$orderTags = $paymentData['order']['order_tags'] ?? [];
|
|
|
|
if (isset($orderTags['plan_id']) && isset($orderTags['user_id'])) {
|
|
processPaymentSuccess([
|
|
'user_id' => $orderTags['user_id'],
|
|
'plan_id' => $orderTags['plan_id'],
|
|
'billing_cycle' => $orderTags['billing_cycle'] ?? 'monthly',
|
|
'payment_method' => 'cashfree',
|
|
'payment_id' => $paymentData['cf_payment_id'],
|
|
]);
|
|
}
|
|
}
|
|
|
|
return response()->json(['status' => 'success']);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => __('Webhook processing failed')], 500);
|
|
}
|
|
}
|
|
} |