184 lines
6.3 KiB
PHP
184 lines
6.3 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Frontend;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use App\Models\MembershipPlan;
|
||
use App\Models\Payment;
|
||
use App\Models\Subscription;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Auth;
|
||
use Illuminate\Support\Str;
|
||
|
||
class CheckoutController extends Controller
|
||
{
|
||
private function options(): \Iyzipay\Options
|
||
{
|
||
$opt = new \Iyzipay\Options();
|
||
$opt->setApiKey(config('iyzico.api_key'));
|
||
$opt->setSecretKey(config('iyzico.secret_key'));
|
||
$opt->setBaseUrl(config('iyzico.base_url'));
|
||
return $opt;
|
||
}
|
||
|
||
public function show(MembershipPlan $plan)
|
||
{
|
||
abort_if(!$plan->is_active || !$plan->is_public, 404);
|
||
return view('frontend.checkout.show', compact('plan'));
|
||
}
|
||
|
||
public function initialize(Request $request, MembershipPlan $plan)
|
||
{
|
||
abort_if(!$plan->is_active || !$plan->is_public, 404);
|
||
|
||
$v = $request->validate([
|
||
'full_name' => 'required|string|max:100',
|
||
'phone' => 'required|string|max:20',
|
||
'city' => 'required|string|max:80',
|
||
'address' => 'required|string|max:300',
|
||
'identity_no' => 'nullable|digits:11',
|
||
]);
|
||
|
||
$user = Auth::user();
|
||
$conversationId = Str::uuid()->toString();
|
||
$price = number_format($plan->price, 2, '.', '');
|
||
|
||
$parts = explode(' ', trim($v['full_name']), 2);
|
||
$firstName = $parts[0];
|
||
$lastName = $parts[1] ?? '-';
|
||
|
||
$payment = Payment::create([
|
||
'user_id' => $user->id,
|
||
'plan_id' => $plan->id,
|
||
'conversation_id' => $conversationId,
|
||
'amount' => $plan->price,
|
||
'status' => 'pending',
|
||
]);
|
||
|
||
$req = new \Iyzipay\Request\CreateCheckoutFormInitializeRequest();
|
||
$req->setLocale(\Iyzipay\Model\Locale::TR);
|
||
$req->setConversationId($conversationId);
|
||
$req->setPrice($price);
|
||
$req->setPaidPrice($price);
|
||
$req->setCurrency(\Iyzipay\Model\Currency::TL);
|
||
$req->setBasketId('payment-' . $payment->id);
|
||
$req->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
|
||
$req->setCallbackUrl(route('checkout.callback'));
|
||
$req->setEnabledInstallments([1, 2, 3, 6, 9, 12]);
|
||
|
||
$buyer = new \Iyzipay\Model\Buyer();
|
||
$buyer->setId('u' . $user->id);
|
||
$buyer->setName($firstName);
|
||
$buyer->setSurname($lastName);
|
||
$buyer->setGsmNumber('+9' . preg_replace('/\D/', '', $v['phone']));
|
||
$buyer->setEmail($user->email);
|
||
$buyer->setIdentityNumber($v['identity_no'] ?: '11111111111');
|
||
$buyer->setRegistrationAddress($v['address']);
|
||
$buyer->setIp($request->ip());
|
||
$buyer->setCity($v['city']);
|
||
$buyer->setCountry('Turkey');
|
||
$req->setBuyer($buyer);
|
||
|
||
$addr = new \Iyzipay\Model\Address();
|
||
$addr->setContactName($v['full_name']);
|
||
$addr->setCity($v['city']);
|
||
$addr->setCountry('Turkey');
|
||
$addr->setAddress($v['address']);
|
||
$req->setBillingAddress($addr);
|
||
$req->setShippingAddress($addr);
|
||
|
||
$item = new \Iyzipay\Model\BasketItem();
|
||
$item->setId('plan' . $plan->id);
|
||
$item->setName($plan->name . ' Premium (' . $plan->duration_days . ' gün)');
|
||
$item->setCategory1('Dijital Ürün');
|
||
$item->setItemType(\Iyzipay\Model\BasketItemType::VIRTUAL);
|
||
$item->setPrice($price);
|
||
$req->setBasketItems([$item]);
|
||
|
||
$form = \Iyzipay\Model\CheckoutFormInitialize::create($req, $this->options());
|
||
|
||
if ($form->getStatus() !== 'success') {
|
||
$payment->update(['status' => 'failed', 'error_message' => $form->getErrorMessage()]);
|
||
return back()->withErrors(['general' => 'Ödeme başlatılamadı: ' . $form->getErrorMessage()]);
|
||
}
|
||
|
||
$payment->update(['token' => $form->getToken()]);
|
||
|
||
return view('frontend.checkout.form', [
|
||
'plan' => $plan,
|
||
'formContent' => $form->getCheckoutFormContent(),
|
||
]);
|
||
}
|
||
|
||
public function callback(Request $request)
|
||
{
|
||
$token = $request->input('token');
|
||
|
||
if (!$token) {
|
||
return redirect()->route('checkout.failed');
|
||
}
|
||
|
||
$payment = Payment::where('token', $token)->where('status', 'pending')->first();
|
||
|
||
if (!$payment) {
|
||
return redirect()->route('checkout.failed');
|
||
}
|
||
|
||
$req = new \Iyzipay\Request\RetrieveCheckoutFormRequest();
|
||
$req->setLocale(\Iyzipay\Model\Locale::TR);
|
||
$req->setConversationId($payment->conversation_id);
|
||
$req->setToken($token);
|
||
|
||
$result = \Iyzipay\Model\CheckoutForm::retrieve($req, $this->options());
|
||
|
||
if ($result->getStatus() === 'success' && $result->getPaymentStatus() === 'SUCCESS') {
|
||
$payment->update([
|
||
'status' => 'success',
|
||
'iyzico_payment_id' => $result->getPaymentId(),
|
||
'paid_at' => now(),
|
||
]);
|
||
|
||
$plan = $payment->plan;
|
||
$user = $payment->user;
|
||
$hasEver = Subscription::where('user_id', $user->id)->exists();
|
||
$bonus = ($hasEver === false && ($plan->trial_days ?? 0) > 0) ? $plan->trial_days : 0;
|
||
$expiresAt = now()->addDays($plan->duration_days + $bonus);
|
||
|
||
Subscription::create([
|
||
'user_id' => $user->id,
|
||
'plan_id' => $plan->id,
|
||
'status' => 'active',
|
||
'starts_at' => now(),
|
||
'expires_at' => $expiresAt,
|
||
'payment_method' => 'iyzico',
|
||
'payment_ref' => $result->getPaymentId(),
|
||
]);
|
||
|
||
$user->update([
|
||
'membership' => 'premium',
|
||
'premium_expires_at' => $expiresAt,
|
||
]);
|
||
|
||
session(['checkout_plan_name' => $plan->name]);
|
||
return redirect()->route('checkout.success');
|
||
}
|
||
|
||
$payment->update([
|
||
'status' => 'failed',
|
||
'error_message' => $result->getErrorMessage(),
|
||
]);
|
||
|
||
return redirect()->route('checkout.failed');
|
||
}
|
||
|
||
public function success()
|
||
{
|
||
return view('frontend.checkout.success');
|
||
}
|
||
|
||
public function failed()
|
||
{
|
||
return view('frontend.checkout.failed');
|
||
}
|
||
}
|