Files
HRM-System/app/Http/Controllers/MolliePaymentController.php
2026-04-13 08:16:56 +08:00

257 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Plan;
use App\Models\PlanOrder;
use App\Models\PaymentSetting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Mollie\Api\MollieApiClient;
class MolliePaymentController extends Controller
{
private function getMollieCredentials()
{
$settings = getPaymentGatewaySettings();
return [
'api_key' => $settings['payment_settings']['mollie_api_key'] ?? null,
'currency' => $settings['general_settings']['defaultCurrency'] ?? 'EUR'
];
}
public function processPayment(Request $request)
{
$validated = $request->validate([
'plan_id' => 'required|exists:plans,id',
'billing_cycle' => 'required|in:monthly,yearly',
'coupon_code' => 'nullable|string',
'customer_details' => 'required|array',
'customer_details.firstName' => 'required|string',
'customer_details.lastName' => 'required|string',
'customer_details.email' => 'required|email'
]);
try {
$plan = Plan::findOrFail($validated['plan_id']);
$pricing = calculatePlanPricing($plan, $validated['coupon_code'] ?? null);
$credentials = $this->getMollieCredentials();
if (!$credentials['api_key']) {
return back()->withErrors(['error' => __('Mollie not configured')]);
}
$paymentId = 'mollie_' . $plan->id . '_' . time() . '_' . uniqid();
// Create pending order
createPlanOrder([
'user_id' => auth()->id(),
'plan_id' => $plan->id,
'billing_cycle' => $validated['billing_cycle'],
'payment_method' => 'mollie',
'coupon_code' => $validated['coupon_code'] ?? null,
'payment_id' => $paymentId,
'status' => 'pending'
]);
// Initialize Mollie SDK
$mollie = new MollieApiClient();
$mollie->setApiKey($credentials['api_key']);
$paymentData = [
'amount' => [
'currency' => $credentials['currency'],
'value' => number_format($pricing['final_price'], 2, '.', '')
],
'description' => 'Plan Subscription - ' . $plan->name,
'redirectUrl' => route('mollie.success'),
'metadata' => [
'payment_id' => $paymentId,
'plan_id' => $plan->id,
'user_id' => auth()->id(),
'billing_cycle' => $validated['billing_cycle']
]
];
// Only add webhook URL if not localhost
if (!str_contains(config('app.url'), 'localhost')) {
$paymentData['webhookUrl'] = route('mollie.callback');
}
$payment = $mollie->payments->create($paymentData);
// Update the plan order with the actual Mollie payment ID
PlanOrder::where('payment_id', $paymentId)
->update(['payment_id' => $payment->id, 'notes' => __('Mollie Payment ID: ') . $payment->id]);
return redirect($payment->getCheckoutUrl());
} catch (\Exception $e) {
return back()->withErrors(['error' => __('Payment failed. Please try again.')]);
}
}
public function createPayment(Request $request)
{
$validated = validatePaymentRequest($request, [
'customer_name' => 'required|string',
'customer_email' => 'required|email',
]);
try {
$plan = Plan::findOrFail($validated['plan_id']);
$pricing = calculatePlanPricing($plan, $validated['coupon_code'] ?? null);
$credentials = $this->getMollieCredentials();
if (!$credentials['api_key']) {
throw new \Exception(__('Mollie API key not configured'));
}
$paymentId = 'mollie_' . $plan->id . '_' . time() . '_' . uniqid();
// Create pending order
createPlanOrder([
'user_id' => auth()->id(),
'plan_id' => $plan->id,
'billing_cycle' => $validated['billing_cycle'],
'payment_method' => 'mollie',
'coupon_code' => $validated['coupon_code'] ?? null,
'payment_id' => $paymentId,
'status' => 'pending'
]);
// Initialize Mollie SDK
$mollie = new MollieApiClient();
$mollie->setApiKey($credentials['api_key']);
$payment = $mollie->payments->create([
'amount' => [
'currency' => $credentials['currency'],
'value' => number_format($pricing['final_price'], 2, '.', '')
],
'description' => 'Plan Subscription - ' . $plan->name,
'redirectUrl' => route('mollie.success'),
'webhookUrl' => route('mollie.callback'),
'metadata' => [
'payment_id' => $paymentId,
'plan_id' => $plan->id,
'user_id' => auth()->id(),
'billing_cycle' => $validated['billing_cycle']
]
]);
// Update the plan order with the actual Mollie payment ID
PlanOrder::where('payment_id', $paymentId)
->update(['payment_id' => $payment->id, 'notes' => 'Mollie Payment ID: ' . $payment->id]);
return response()->json([
'success' => true,
'payment_id' => $payment->id,
'checkout_url' => $payment->getCheckoutUrl()
]);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
public function checkPaymentStatus(Request $request)
{
$validated = $request->validate([
'payment_id' => 'required|string'
]);
try {
$credentials = $this->getMollieCredentials();
$mollie = new MollieApiClient();
$mollie->setApiKey($credentials['api_key']);
$payment = $mollie->payments->get($validated['payment_id']);
return response()->json([
'status' => $payment->status,
'is_paid' => $payment->isPaid(),
'is_failed' => $payment->isFailed(),
'is_canceled' => $payment->isCanceled()
]);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
public function success(Request $request)
{
try {
$credentials = $this->getMollieCredentials();
if (!$credentials['api_key']) {
return redirect()->route('plans.index')->with('error', __('Payment configuration error.'));
}
// Find the most recent pending order for this user
$userId = auth()->id();
if ($userId) {
$planOrder = PlanOrder::where('user_id', $userId)
->where('status', 'pending')
->where('payment_method', 'mollie')
->orderBy('created_at', 'desc')
->first();
if ($planOrder) {
$mollie = new MollieApiClient();
$mollie->setApiKey($credentials['api_key']);
try {
$payment = $mollie->payments->get($planOrder->payment_id);
if ($payment->isPaid()) {
$planOrder->update(['status' => 'approved']);
$planOrder->activateSubscription();
return redirect()->route('plans.index')->with('success', __('Payment completed successfully! Your plan has been activated.'));
} elseif ($payment->status === 'pending') {
return redirect()->route('plans.index')->with('info', __('Payment is being processed. Your plan will be activated shortly.'));
} else {
return redirect()->route('plans.index')->with('error', __('Payment was not successful. Please try again.'));
}
} catch (\Exception $e) {
return redirect()->route('plans.index')->with('info', __('Payment is being processed. Your plan will be activated shortly.'));
}
}
}
return redirect()->route('plans.index')->with('info', __('Payment is being processed. Your plan will be activated shortly.'));
} catch (\Exception $e) {
return redirect()->route('plans.index')->with('error', __('Payment verification failed. Please contact support.'));
}
}
public function callback(Request $request)
{
try {
$paymentId = $request->input('id');
$credentials = $this->getMollieCredentials();
$mollie = new MollieApiClient();
$mollie->setApiKey($credentials['api_key']);
$payment = $mollie->payments->get($paymentId);
if ($payment->isPaid()) {
$planOrder = PlanOrder::where('payment_id', $paymentId)->first();
if ($planOrder && $planOrder->status === 'pending') {
$planOrder->update(['status' => 'approved']);
$planOrder->activateSubscription();
}
}
return response('OK', 200);
} catch (\Exception $e) {
return response('ERROR', 500);
}
}
}