Fix payment form validation, styling and blog header visibility
This commit is contained in:
@@ -21,7 +21,7 @@ class BlogCategoryResource extends Resource
|
|||||||
{
|
{
|
||||||
protected static ?string $model = BlogCategory::class;
|
protected static ?string $model = BlogCategory::class;
|
||||||
|
|
||||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedTag;
|
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-tag';
|
||||||
|
|
||||||
protected static UnitEnum|string|null $navigationGroup = 'Blog';
|
protected static UnitEnum|string|null $navigationGroup = 'Blog';
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class BlogResource extends Resource
|
|||||||
{
|
{
|
||||||
protected static ?string $model = Blog::class;
|
protected static ?string $model = Blog::class;
|
||||||
|
|
||||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDocumentText;
|
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
|
||||||
|
|
||||||
public static function getNavigationLabel(): string
|
public static function getNavigationLabel(): string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class PageSettingsSection
|
|||||||
'corporate.logos' => 'Logolarımız (Kurumsal)',
|
'corporate.logos' => 'Logolarımız (Kurumsal)',
|
||||||
'corporate.partners' => 'Çözüm Ortaklarımız (Kurumsal)',
|
'corporate.partners' => 'Çözüm Ortaklarımız (Kurumsal)',
|
||||||
'corporate.bank-accounts' => 'Banka Bilgilerimiz (Kurumsal)',
|
'corporate.bank-accounts' => 'Banka Bilgilerimiz (Kurumsal)',
|
||||||
|
'corporate.online-payment' => 'Online Ödeme (Kurumsal)',
|
||||||
])
|
])
|
||||||
->default('default')
|
->default('default')
|
||||||
->columnSpanFull(),
|
->columnSpanFull(),
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ class BlogController extends Controller
|
|||||||
$headerTemplate = HeaderTemplate::find($blogPage->header_template_id);
|
$headerTemplate = HeaderTemplate::find($blogPage->header_template_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Öncelik: Varsayılan aktif template
|
// 2. Öncelik: Varsayılan aktif template (KALDIRILDI - Default static header kullanılmalı)
|
||||||
|
/*
|
||||||
if (!$headerTemplate) {
|
if (!$headerTemplate) {
|
||||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
$headerTemplate = HeaderTemplate::where('is_active', true)
|
||||||
->latest('updated_at')
|
->latest('updated_at')
|
||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if ($headerTemplate) {
|
if ($headerTemplate) {
|
||||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||||
@@ -164,17 +166,26 @@ class BlogController extends Controller
|
|||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Render Header Template - En son aktif olan header template'i kullan
|
// Blog sayfa ayarlarını bul (varsa)
|
||||||
|
$blogPage = Page::where('slug', 'blog')->first();
|
||||||
|
|
||||||
|
// Render Header Template
|
||||||
$renderedHeader = null;
|
$renderedHeader = null;
|
||||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
$headerTemplate = null;
|
||||||
->latest('updated_at')
|
|
||||||
->first();
|
// 1. Öncelik: Blog sayfasında seçili header template
|
||||||
|
if ($blogPage && $blogPage->header_template_id) {
|
||||||
|
$headerTemplate = HeaderTemplate::find($blogPage->header_template_id);
|
||||||
|
}
|
||||||
|
|
||||||
if ($headerTemplate) {
|
if ($headerTemplate) {
|
||||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||||
|
$pageData = $blogPage ? ($blogPage->header_data ?? []) : [];
|
||||||
|
$mergedData = array_merge($templateDefaults, $pageData);
|
||||||
|
|
||||||
$renderedHeader = TemplateService::replacePlaceholders(
|
$renderedHeader = TemplateService::replacePlaceholders(
|
||||||
$headerTemplate->html_content,
|
$headerTemplate->html_content,
|
||||||
$templateDefaults,
|
$mergedData,
|
||||||
$post
|
$post
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Page;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
class PaymentController extends Controller
|
||||||
|
{
|
||||||
|
public function process(Request $request)
|
||||||
|
{
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'surname' => 'required|string|max:255',
|
||||||
|
'email' => 'required|email|max:255',
|
||||||
|
'phone' => 'required|string|max:20',
|
||||||
|
'price' => 'required|numeric|min:1',
|
||||||
|
'address' => 'required|string',
|
||||||
|
'agreement' => 'accepted',
|
||||||
|
], [
|
||||||
|
'name.required' => 'Lütfen adınızı giriniz.',
|
||||||
|
'surname.required' => 'Lütfen soyadınızı giriniz.',
|
||||||
|
'email.required' => 'Lütfen e-posta adresinizi giriniz.',
|
||||||
|
'email.email' => 'Geçerli bir e-posta adresi giriniz.',
|
||||||
|
'phone.required' => 'Lütfen telefon numaranızı giriniz.',
|
||||||
|
'price.required' => 'Lütfen ödeme tutarını giriniz.',
|
||||||
|
'price.min' => 'Ödeme tutarı en az 1 TL olmalıdır.',
|
||||||
|
'address.required' => 'Lütfen ödeme açıklamasını giriniz.',
|
||||||
|
'agreement.accepted' => 'Lütfen sözleşmeyi onaylayınız.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
Log::info('Payment Validation Failed', $validator->errors()->toArray());
|
||||||
|
|
||||||
|
return back()->withErrors($validator)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
$merchant_id = '127117';
|
||||||
|
$merchant_key = 's9GH5FMuxFtqjxyJ';
|
||||||
|
$merchant_salt = 'qTHTx3j4FjieXPP3';
|
||||||
|
|
||||||
|
$price = $request->input('price') * 100; // Krş cinsinden
|
||||||
|
|
||||||
|
// Get user IP (handling Cloudflare or standard)
|
||||||
|
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
|
||||||
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||||
|
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||||
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||||
|
} else {
|
||||||
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
$user_ip = $ip;
|
||||||
|
|
||||||
|
$merchant_oid = time(); // Benzersiz sipariş no
|
||||||
|
$email = $request->input('email');
|
||||||
|
$payment_amount = $price;
|
||||||
|
$currency = 'TL'; // Default
|
||||||
|
$test_mode = 0; // Canlı mod
|
||||||
|
|
||||||
|
$user_name = $request->input('name').' '.$request->input('surname');
|
||||||
|
$user_address = $request->input('address'); // Note field used as address
|
||||||
|
$user_phone = $request->input('phone');
|
||||||
|
|
||||||
|
// Callbacks should ideally be routes we define, but user provided specific URLs.
|
||||||
|
// We will use routes relative to current domain or the ones user specified if they are absolute?
|
||||||
|
// The user script had: "https://www.truncgil.com.tr/pay.php?ok"
|
||||||
|
// I should probably use the current app's URL.
|
||||||
|
$merchant_ok_url = route('payment.success');
|
||||||
|
$merchant_fail_url = route('payment.fail');
|
||||||
|
|
||||||
|
$user_basket = base64_encode(json_encode([
|
||||||
|
['Web / Mobil Yazılım', $payment_amount, 1],
|
||||||
|
]));
|
||||||
|
|
||||||
|
$no_installment = 0;
|
||||||
|
$max_installment = 9;
|
||||||
|
$debug_on = 1;
|
||||||
|
$timeout_limit = 30;
|
||||||
|
|
||||||
|
$hash_str = $merchant_id.$user_ip.$merchant_oid.$email.$payment_amount.$user_basket.$no_installment.$max_installment.$currency.$test_mode;
|
||||||
|
$paytr_token = base64_encode(hash_hmac('sha256', $hash_str.$merchant_salt, $merchant_key, true));
|
||||||
|
|
||||||
|
$post_vals = [
|
||||||
|
'merchant_id' => $merchant_id,
|
||||||
|
'user_ip' => $user_ip,
|
||||||
|
'merchant_oid' => $merchant_oid,
|
||||||
|
'email' => $email,
|
||||||
|
'lang' => 'tr',
|
||||||
|
'payment_amount' => $payment_amount,
|
||||||
|
'paytr_token' => $paytr_token,
|
||||||
|
'user_basket' => $user_basket,
|
||||||
|
'debug_on' => $debug_on,
|
||||||
|
'no_installment' => $no_installment,
|
||||||
|
'max_installment' => $max_installment,
|
||||||
|
'user_name' => $user_name,
|
||||||
|
'user_address' => $user_address,
|
||||||
|
'user_phone' => $user_phone,
|
||||||
|
'merchant_ok_url' => $merchant_ok_url,
|
||||||
|
'merchant_fail_url' => $merchant_fail_url,
|
||||||
|
'timeout_limit' => $timeout_limit,
|
||||||
|
'currency' => $currency,
|
||||||
|
'test_mode' => $test_mode,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Curl request
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, 'https://www.paytr.com/odeme/api/get-token');
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_vals);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
||||||
|
$result = @curl_exec($ch);
|
||||||
|
|
||||||
|
if (curl_errno($ch)) {
|
||||||
|
return back()->with('error', 'PAYTR connection error. err:'.curl_error($ch));
|
||||||
|
}
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$result = json_decode($result, 1);
|
||||||
|
|
||||||
|
if ($result['status'] == 'success') {
|
||||||
|
$token = $result['token'];
|
||||||
|
|
||||||
|
// Re-render the online-payment page but with the token
|
||||||
|
// We need to fetch the page content again
|
||||||
|
// Assuming the slug is 'online-odeme' or similar, or we can just pass a dummy page object
|
||||||
|
// if we are lazy, but correct way is to fetch the page associated with the route.
|
||||||
|
// Since we are POSTing here, we don't know the Page model context unless we fetch it.
|
||||||
|
// Let's try to assume 'online-odeme' which is common.
|
||||||
|
|
||||||
|
$page = Page::where('template', 'online-payment')->orWhere('slug', 'online-odeme')->first();
|
||||||
|
if (! $page) {
|
||||||
|
$page = new Page(['title' => 'Online Ödeme', 'content' => '', 'excerpt' => 'Please complete your payment below.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('templates.corporate.online-payment', [
|
||||||
|
'page' => $page,
|
||||||
|
'paytr_token' => $token,
|
||||||
|
]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return back()->with('error', 'PAYTR failed. reason:'.$result['reason']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function success(Request $request)
|
||||||
|
{
|
||||||
|
$page = Page::where('template', 'online-payment')->orWhere('slug', 'online-odeme')->first();
|
||||||
|
if ($page) {
|
||||||
|
return redirect()->route('page.show', $page->slug)->with('success', 'Your payment has been charged successfully. This will appear on your credit card statement as "PAYTR ODEME HIZMETLERI"');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('home')->with('success', 'Your payment has been charged successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fail(Request $request)
|
||||||
|
{
|
||||||
|
$page = Page::where('template', 'online-payment')->orWhere('slug', 'online-odeme')->first();
|
||||||
|
if ($page) {
|
||||||
|
return redirect()->route('page.show', $page->slug)->with('error', 'Your payment has not been charged successfully! Please check your credit card information.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('home')->with('error', 'Your payment has not been charged successfully! Please check your credit card information.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,13 +11,6 @@ use Illuminate\Auth\Access\HandlesAuthorization;
|
|||||||
class PagePolicy
|
class PagePolicy
|
||||||
{
|
{
|
||||||
use HandlesAuthorization;
|
use HandlesAuthorization;
|
||||||
|
|
||||||
public function before(AuthUser $user, $ability)
|
|
||||||
{
|
|
||||||
if ($user->hasRole('super_admin')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function viewAny(AuthUser $authUser): bool
|
public function viewAny(AuthUser $authUser): bool
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\User as AuthUser;
|
||||||
|
use App\Models\ProductCategory;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class ProductCategoryPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
public function viewAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ViewAny:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('View:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Create:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Update:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Delete:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restore(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Restore:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDelete(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDelete:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDeleteAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDeleteAny:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restoreAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('RestoreAny:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replicate(AuthUser $authUser, ProductCategory $productCategory): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Replicate:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reorder(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Reorder:ProductCategory');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\User as AuthUser;
|
||||||
|
use App\Models\Product;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class ProductPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
public function viewAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ViewAny:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('View:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Create:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Update:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Delete:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restore(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Restore:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDelete(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDelete:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDeleteAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDeleteAny:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restoreAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('RestoreAny:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replicate(AuthUser $authUser, Product $product): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Replicate:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reorder(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Reorder:Product');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\User as AuthUser;
|
||||||
|
use App\Models\SiteTranslation;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class SiteTranslationPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
public function viewAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ViewAny:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('View:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Create:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Update:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Delete:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restore(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Restore:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDelete(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDelete:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forceDeleteAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('ForceDeleteAny:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restoreAny(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('RestoreAny:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replicate(AuthUser $authUser, SiteTranslation $siteTranslation): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Replicate:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reorder(AuthUser $authUser): bool
|
||||||
|
{
|
||||||
|
return $authUser->can('Reorder:SiteTranslation');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('visions', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('visions');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
@extends('layouts.site')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<section class="wrapper bg-white py-14 xl:py-20 relative">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-center mb-12">
|
||||||
|
<div class="col-lg-8 mx-auto text-center">
|
||||||
|
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-orange-100 text-orange-600 text-sm font-bold mb-4">
|
||||||
|
<i class="uil uil-shield-check text-lg"></i>
|
||||||
|
{!! t('256-Bit SSL Güvenli Ödeme') !!}
|
||||||
|
</div>
|
||||||
|
<h1 class="display-3 font-bold text-slate-800 mb-3">{!! $page->title !!}</h1>
|
||||||
|
<p class="lead text-slate-500 max-w-2xl mx-auto">{!! $page->excerpt ?? t('Kredi kartınızla hızlı, kolay ve güvenli ödeme yapın.') !!}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
<div class="row mb-8">
|
||||||
|
<div class="col-lg-8 mx-auto">
|
||||||
|
<div class="alert alert-success bg-green-100 text-green-700 border-green-200 rounded-xl p-4 flex items-center gap-3">
|
||||||
|
<i class="uil uil-check-circle text-2xl"></i>
|
||||||
|
<div>
|
||||||
|
<h4 class="font-bold text-lg mb-1">{!! t('Ödeme Başarılı!') !!}</h4>
|
||||||
|
<p>{!! session('success') !!}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(session('error'))
|
||||||
|
<div class="row mb-8">
|
||||||
|
<div class="col-lg-8 mx-auto">
|
||||||
|
<div class="alert alert-danger bg-red-100 text-red-700 border-red-200 rounded-xl p-4 flex items-center gap-3">
|
||||||
|
<i class="uil uil-exclamation-triangle text-2xl"></i>
|
||||||
|
<div>
|
||||||
|
<h4 class="font-bold text-lg mb-1">{!! t('Ödeme Başarısız!') !!}</h4>
|
||||||
|
<p>{!! session('error') !!}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="row mb-8">
|
||||||
|
<div class="col-lg-8 mx-auto">
|
||||||
|
<div class="alert alert-danger p-4 rounded-xl border border-red-200 bg-red-50" style="background-color: #fef2f2 !important; border-color: #fecaca !important;">
|
||||||
|
<div class="flex items-center gap-3 mb-2" style="color: #dc2626 !important;">
|
||||||
|
<i class="uil uil-exclamation-triangle text-2xl"></i>
|
||||||
|
<h4 class="font-bold text-lg mb-0" style="color: #dc2626 !important;">{!! t('Lütfen Bilgileri Kontrol Ediniz') !!}</h4>
|
||||||
|
</div>
|
||||||
|
<ul class="list-disc pl-10 mb-0 font-medium" style="color: #dc2626 !important;">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-10 col-xl-9">
|
||||||
|
@if(isset($paytr_token))
|
||||||
|
<div class="card shadow-lg border-0 rounded-3xl overflow-hidden relative" style="min-height: 500px;">
|
||||||
|
<!-- Üst Turuncu Çizgi -->
|
||||||
|
<div class="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-orange-500 to-amber-500"></div>
|
||||||
|
<div class="card-body p-4 bg-white">
|
||||||
|
<script src="https://www.paytr.com/js/iframeResizer.min.js"></script>
|
||||||
|
<iframe src="https://www.paytr.com/odeme/guvenli/{!! $paytr_token !!}" id="paytriframe" frameborder="0" scrolling="no" style="width: 100%;"></iframe>
|
||||||
|
<script>iFrameResize({},'#paytriframe');</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="card shadow-lg border-0 rounded-3xl overflow-hidden relative">
|
||||||
|
<!-- Üst Turuncu Çizgi -->
|
||||||
|
<div class="absolute top-0 left-0 w-full h-2 bg-gradient-to-r from-orange-500 to-amber-500"></div>
|
||||||
|
|
||||||
|
<div class="card-body p-0">
|
||||||
|
|
||||||
|
|
||||||
|
<form action="{{ route('payment.process') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="payment_type" value="online">
|
||||||
|
|
||||||
|
<div class="row g-0">
|
||||||
|
<!-- Sol Taraf: Ödeme Formu -->
|
||||||
|
<div class="col-lg-7 p-8 md:p-10 bg-white">
|
||||||
|
<h3 class="h4 mb-6 text-slate-800 font-bold flex items-center gap-2">
|
||||||
|
<div class="w-8 h-8 rounded-full bg-orange-100 flex items-center justify-center text-orange-600 text-sm">1</div>
|
||||||
|
{!! t('Kart Sahibi Bilgileri') !!}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label text-slate-700 font-bold mb-2">{!! t('Adınız') !!}</label>
|
||||||
|
<input type="text" name="name" class="form-control bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-3 @error('name') border-red-500 @enderror" id="name" placeholder="{!! t('Adınızı Giriniz') !!}" value="{{ old('name') }}">
|
||||||
|
@error('name') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="surname" class="form-label text-slate-700 font-bold mb-2">{!! t('Soyadınız') !!}</label>
|
||||||
|
<input type="text" name="surname" class="form-control bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-3 @error('surname') border-red-500 @enderror" id="surname" placeholder="{!! t('Soyadınızı Giriniz') !!}" value="{{ old('surname') }}">
|
||||||
|
@error('surname') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label text-slate-700 font-bold mb-2">{!! t('E-Posta Adresi') !!}</label>
|
||||||
|
<input type="email" name="email" class="form-control bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-3 @error('email') border-red-500 @enderror" id="email" placeholder="{!! t('E-Posta Adresinizi Giriniz') !!}" value="{{ old('email') }}">
|
||||||
|
@error('email') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="phone" class="form-label text-slate-700 font-bold mb-2">{!! t('Telefon Numarası') !!}</label>
|
||||||
|
<input type="tel" name="phone" class="form-control bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-3 @error('phone') border-red-500 @enderror" id="phone" placeholder="{!! t('Telefon Numaranızı Giriniz') !!}" value="{{ old('phone') }}">
|
||||||
|
@error('phone') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="address" class="form-label text-slate-700 font-bold mb-2">{!! t('Ödeme Açıklaması / Not') !!}</label>
|
||||||
|
<textarea name="address" class="form-control bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-3 @error('address') border-red-500 @enderror" id="address" placeholder="{!! t('Varsa notunuzu buraya yazabilirsiniz...') !!}" style="height: 100px;">{{ old('address') }}</textarea>
|
||||||
|
@error('address') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 pt-6 border-t border-slate-100">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input border-slate-300 checked:bg-orange-500 checked:border-orange-500 focus:ring-orange-200 @error('agreement') border-red-500 @enderror" type="checkbox" name="agreement" value="1" id="policyCheck" {{ old('agreement') ? 'checked' : '' }}>
|
||||||
|
<label class="form-check-label text-sm text-slate-500" for="policyCheck">
|
||||||
|
{!! t('<a href="#" class="text-orange-600 hover:text-orange-700 font-medium">Mesafeli Satış Sözleşmesi</a>\'ni okudum, onaylıyorum.') !!}
|
||||||
|
</label>
|
||||||
|
@error('agreement') <div class="text-red-600 text-sm mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Sağ Taraf: Özet ve Tutar -->
|
||||||
|
<div class="col-lg-5 bg-slate-50 p-8 md:p-10 border-l border-slate-100 flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 class="h4 mb-6 text-slate-800 font-bold flex items-center gap-2">
|
||||||
|
<div class="w-8 h-8 rounded-full bg-slate-200 flex items-center justify-center text-slate-600 text-sm">2</div>
|
||||||
|
{!! t('Ödeme Tutarı') !!}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm text-center mb-6">
|
||||||
|
<label class="block text-xs font-bold text-slate-400 uppercase tracking-wider mb-2">{!! t('TOPLAM TUTAR') !!}</label>
|
||||||
|
<div class="relative inline-block w-full">
|
||||||
|
<span class="absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-orange-500">₺</span>
|
||||||
|
<input type="number" step="0.01" min="1" name="price" class="form-control border-0 bg-transparent text-center text-4xl font-bold text-slate-800 p-0 focus:ring-0 focus:shadow-none w-full @error('price') text-red-500 @enderror" placeholder="0.00" id="amount" value="{{ old('price') }}">
|
||||||
|
</div>
|
||||||
|
@error('price') <div class="text-red-600 text-xs mt-1 font-medium">{{ $message }}</div> @enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-3 opacity-70">
|
||||||
|
<div class="flex items-center gap-3 text-sm text-slate-600">
|
||||||
|
<i class="uil uil-check-circle text-green-500 text-lg"></i>
|
||||||
|
<span>{!! t('Komisyonsuz İşlem') !!}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3 text-sm text-slate-600">
|
||||||
|
<i class="uil uil-check-circle text-green-500 text-lg"></i>
|
||||||
|
<span>{!! t('3D Secure ile Maksimum Güvenlik') !!}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8">
|
||||||
|
<button type="submit" class="btn w-full rounded-xl py-3 px-6 text-white font-bold text-lg shadow-lg hover:-translate-y-1 transition-all duration-300 flex items-center justify-center gap-2" style="background-color: #dc2626 !important; color: #ffffff !important; box-shadow: 0 4px 6px -1px rgba(220, 38, 38, 0.5);">
|
||||||
|
<i class="uil uil-padlock"></i>
|
||||||
|
<span>{!! t('ÖDEMEYİ TAMAMLA') !!}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="mt-6 flex justify-center gap-4 opacity-50 grayscale hover:grayscale-0 transition-all duration-300">
|
||||||
|
<i class="uil uil-master-card text-3xl"></i>
|
||||||
|
<i class="uil uil-visa text-3xl"></i>
|
||||||
|
<i class="uil uil-card-atm text-3xl"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($page->content)
|
||||||
|
<div class="mt-14 text-center">
|
||||||
|
<div class="prose max-w-3xl mx-auto text-slate-600">
|
||||||
|
{!! $page->content !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
@endsection
|
||||||
@@ -100,6 +100,11 @@ Route::prefix('admin/api')->middleware(['auth', \App\Http\Middleware\SuperAdminM
|
|||||||
// Products & Services
|
// Products & Services
|
||||||
Route::get('/urun-hizmet/{slug}', [\App\Http\Controllers\ProductController::class, 'show'])->name('products.show');
|
Route::get('/urun-hizmet/{slug}', [\App\Http\Controllers\ProductController::class, 'show'])->name('products.show');
|
||||||
|
|
||||||
|
// Payment Process
|
||||||
|
Route::post('/payment/process', [\App\Http\Controllers\PaymentController::class, 'process'])->name('payment.process');
|
||||||
|
Route::any('/payment/success', [\App\Http\Controllers\PaymentController::class, 'success'])->name('payment.success');
|
||||||
|
Route::any('/payment/fail', [\App\Http\Controllers\PaymentController::class, 'fail'])->name('payment.fail');
|
||||||
|
|
||||||
// Logo Preview
|
// Logo Preview
|
||||||
Route::get('/logo-preview', function (Illuminate\Http\Request $request) {
|
Route::get('/logo-preview', function (Illuminate\Http\Request $request) {
|
||||||
$path = $request->query('path');
|
$path = $request->query('path');
|
||||||
|
|||||||
Reference in New Issue
Block a user