<?php // تأكد من تثبيت مكتبة apple-signin-php باستخدام Composer require_once 'vendor/autoload.php'; use AppleSignIn\ASDecoder; // إعدادات قاعدة البيانات $servername = "localhost"; $username = "nullsafety_app"; $password = "gQ0T(DHze!5L"; $dbname = "nullsafety_app"; // إعدادات Apple Sign In $LOGIN_APPLE_CLIENT_ID = "io.fitness.club"; $LOGIN_APPLE_SECRET = "eyJraWQiOiJMQ1hESDJSTDJSIiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiI2TFRESjJITldZIiwiaWF0IjoxNjk3MTQ2MDU2LCJleHAiOjE3MTI2OTgwNTYsImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJpby5maXRuZXNzLmNsdWIifQ.D4YPbDBiRv76ToNUa9Lll1F82uohsgIUzIN4x-NBNahfZuC_A8LTNzFuaBDCBp4m5ohPa9eTc2xoK4NRJjWJWA"; // إنشاء اتصال $conn = new mysqli($servername, $username, $password, $dbname); // التحقق من الاتصال if ($conn->connect_error) { die("فشل الاتصال: " . $conn->connect_error); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { // استلام البيانات من Apple $id_token = $_POST['id_token']; try { // فك تشفير وتحقق من الـ token $appleSignInPayload = ASDecoder::getAppleSignInPayload($id_token); // استخراج معلومات المستخدم $email = $appleSignInPayload->getEmail(); $user_id = $appleSignInPayload->getUser(); // الاسم غير متوفر دائمًا، لذا نحتاج للتحقق $name = isset($_POST['user']) ? json_decode($_POST['user'])->name : null; // التحقق مما إذا كان المستخدم موجودًا بالفعل $stmt = $conn->prepare("SELECT id FROM users WHERE apple_id = ?"); $stmt->bind_param("s", $user_id); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { // المستخدم موجود بالفعل، قم بتحديث المعلومات إذا لزم الأمر $stmt = $conn->prepare("UPDATE users SET email = ?, name = ? WHERE apple_id = ?"); $stmt->bind_param("sss", $email, $name, $user_id); } else { // مستخدم جديد، قم بإدراجه في قاعدة البيانات $stmt = $conn->prepare("INSERT INTO users (apple_id, email, name) VALUES (?, ?, ?)"); $stmt->bind_param("sss", $user_id, $email, $name); } if ($stmt->execute()) { echo "تم تسجيل الدخول وحفظ البيانات بنجاح!"; } else { echo "حدث خطأ أثناء حفظ البيانات: " . $stmt->error; } } catch (Exception $e) { echo "حدث خطأ: " . $e->getMessage(); } } $conn->close(); ?> <!DOCTYPE html> <html> <head> <title>تسجيل الدخول باستخدام Apple</title> </head> <body> <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div> <script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> <script type="text/javascript"> AppleID.auth.init({ clientId : '<?php echo $LOGIN_APPLE_CLIENT_ID; ?>', scope : 'name email', redirectURI : 'https://developer.null-safety.com/', state : 'YOUR_STATE_VALUE' }); </script> </body> </html>
if (!function_exists('dd')) { function dd(...$vars) { // ألوان مختلفة ومتناغمة $colors = [ '#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c2c2f0', '#ffb3e6', '#c2f0c2', '#ffccff', '#ffb3b3', '#c2c2c2' ]; $colorCount = count($colors); // الحصول على معلومات إضافية $backtrace = debug_backtrace(); $debugInfo = [ 'line' => $backtrace[0]['line'], 'file' => $backtrace[0]['file'], 'function' => $backtrace[1]['function'] ?? 'N/A', 'request' => $_REQUEST, 'session' => $_SESSION ?? [] ]; // عرض المعلومات الافتراضية إذا لم يتم تمرير أي متغيرات if (empty($vars)) { $vars[] = [ 'file' => $debugInfo['file'], 'line' => $debugInfo['line'], 'function' => $debugInfo['function'], 'request' => $debugInfo['request'], 'session' => $debugInfo['session'], ]; } echo '<div style="font-family: Arial, sans-serif; line-height: 1.5;">'; foreach ($vars as $index => $var) { // حدد اللون بناءً على الفهرس $color = $colors[$index % $colorCount]; echo '<div style="background-color: ' . $color . '; padding: 10px; border-radius: 5px; margin-bottom: 10px; color: #fff;">'; // عنوان البلوك echo '<strong>Breakpoint (' . $debugInfo['file'] . ' on line ' . $debugInfo['line'] . ') ---> Function: ' . $debugInfo['function'] . '</strong><br>'; echo '<strong>Request Data:</strong><br>'; echo '<pre>' . json_encode($debugInfo['request'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>'; echo '<strong>Session Data:</strong><br>'; echo '<pre>' . json_encode($debugInfo['session'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>'; // عرض المتغيرات echo '<strong>Variable ' . ($index + 1) . ':</strong><br>'; if (is_array($var) || is_object($var)) { echo '<pre>' . json_encode($var, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</pre>'; } elseif (is_bool($var) || is_null($var)) { var_dump($var); } else { echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8'); } echo '</div>'; } echo '</div>'; die(1); } }
<?php namespace App\Http\Controllers\Callback; use App\Models\Gig; use App\Models\User; use App\Models\Order; use Razorpay\Api\Api; use App\Models\OrderItem; use App\Models\GigUpgrade; use Illuminate\Support\Str; use App\Models\OrderInvoice; use Illuminate\Http\Request; use App\Models\DepositWebhook; use App\Models\CheckoutWebhook; use App\Models\OrderItemUpgrade; use App\Models\DepositTransaction; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Http; use App\Models\AutomaticPaymentGateway; use App\Notifications\User\Buyer\OrderPlaced; use App\Notifications\User\Seller\PendingOrder; class RazorpayController extends Controller { public $gateway = "razorpay"; public $status = "paid"; public $settings; /** * Payment gateway callback * * @param Request $request * @return mixed */ public function callback(Request $request) { try { // Get payment gateway settings $settings = AutomaticPaymentGateway::where('slug', $this->gateway) ->where('is_active', true) ->firstOrFail(); // Set settings $this->settings = $settings; // Get payment id $payment_id = $request->get('payment_id'); // Get order id $order_id = $request->get('order_id'); // Get signature $signature = $request->get('signature'); // Get action $action = $request->get('action'); // Check webhook event if ( $payment_id && $order_id && $signature ) { // Check if payment succeeded $response = $this->verify($payment_id, $order_id, $signature); // Check if payment succeeded if ( is_array($response) && $response['success'] === TRUE) { // Check if deposit callback if ($action === "D") { // Get saved webhook data in our database $data = DepositWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Handle deposit callback $this->deposit($data->user_id, $data->amount, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('deposit'); } // Check if checkout callback if ($action === "G") { // Get saved webhook data in our database $data = CheckoutWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Get cart $cart = $data->data['cart']; // Get user $user = User::where('id', $data->data['buyer_id'])->firstOrFail(); // Handle deposit callback $this->checkout($cart, $user, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('gigs'); } } } // In case failed redirect to home page return redirect('/'); } catch (\Throwable $th) { // Error throw $th; } } /** * Verify if payment succeeded * * @param string $id * @return array */ private function verify($payment_id, $order_id, $signature) { try { // Get payment gateway keys $key_id = $this->settings?->settings['key_id']; $key_secret = $this->settings?->settings['key_secret']; // Set api $api = new Api($key_id, $key_secret); // Let's verify first the signature $api->utility->verifyPaymentSignature([ 'razorpay_signature' => $signature, 'razorpay_payment_id' => $payment_id, 'razorpay_order_id' => $order_id ]); // Fetch this payment $fetch_payment = $api->payment->fetch($payment_id); // Check if payment authorized if ($fetch_payment->status === 'authorized') { // Let capture this payment $payment = $api->payment->fetch($payment_id)->capture([ 'amount' => $fetch_payment->amount, 'currency' => $fetch_payment->currency ]); } else if ($fetch_payment->status === 'captured') { // Set payment $payment = $fetch_payment; } else { // Payment failed return [ 'success' => false, 'message' => __('messages.t_we_could_not_handle_ur_payment') ]; } // Check if payment succeeded if ( $payment && $payment->status === 'captured' ) { // Done return [ 'success' => true, 'response' => $payment ]; } else { // Failed return [ 'success' => false, 'message' => __('messages.t_error_stripe_payment_failed') ]; } } catch (\Throwable $th) { // Error return [ 'success' => false, 'message' => __('messages.t_toast_something_went_wrong') ]; } } /** * Deposit funds into user's account * * @param int $user_id * @param mixed $amount * @param string $payment_id * @return void */ private function deposit($user_id, $amount, $payment_id) { try { // Set amount $amount = convertToNumber($amount); // Calculate fee from this amount $fee = convertToNumber($this->fee('deposit', $amount)); // Make transaction $deposit = new DepositTransaction(); $deposit->user_id = $user_id; $deposit->transaction_id = $payment_id; $deposit->payment_method = $this->gateway; $deposit->amount_total = $amount; $deposit->amount_fee = $fee; $deposit->amount_net = $amount - $fee; $deposit->currency = $this->settings->currency; $deposit->exchange_rate = $this->settings->exchange_rate; $deposit->status = $this->status; $deposit->ip_address = request()->ip(); $deposit->save(); // Get user $user = User::where('id', $user_id)->firstOrFail(); // Add funds $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net); $user->save(); // Send a notification $this->notification('deposit', $user); } catch (\Throwable $th) { // Error throw $th; } } /** * Checkout * * @param array $cart * @param object $user * @param string $payment_id * @return void */ private function checkout($cart, $user, $payment_id) { try { // Set empty variables $subtotal = 0; $total = 0; $tax = 0; $fee = 0; // Loop through items in cart foreach ($cart as $key => $item) { // Add gig price to subtotal $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']); // Check if item has upgrades $upgrades = $item['upgrades']; // Loop through upgrades if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) { // Loop through upgrades foreach ($upgrades as $j => $upgrade) { // Check if upgrade checked if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Add upgrade price to subtotal $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']); } } } } // Get commission settings $commission_settings = settings('commission'); // Check if taxes enabled if ($commission_settings->enable_taxes) { // Check if type of taxes percentage if ($commission_settings->tax_type === 'percentage') { // Set tax amount $tax = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100); } else { // Set tax amount $tax = convertToNumber($commission_settings->tax_value); } } // Calculate payment gateway fee $fee = convertToNumber($this->fee( 'gigs', $subtotal )); // Calculate total price $total = $subtotal + $tax + $fee; // Get user billing address $billing_info = $user->billing; // Set unique id for this order $uid = uid(); // Get buyer id $buyer_id = $user->id; // Save order $order = new Order(); $order->uid = $uid; $order->buyer_id = $buyer_id; $order->total_value = $total; $order->subtotal_value = $subtotal; $order->taxes_value = $tax; $order->save(); // Loop through items in cart foreach ($cart as $key => $item) { // Get gig $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first(); // Check if gig exists if ($gig) { // Set quantity $quantity = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1; // Set gig upgrades $upgrades = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : []; // Set empty variable $upgrades_amount = 0; // Loop through upgrades foreach ($upgrades as $index => $upgrade) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { $upgrades_amount += convertToNumber($upgrade['price']) * $quantity; } } // Set item total price $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity ); // Calculate commission first if ($commission_settings->commission_from === 'orders') { // Check commission type if ($commission_settings->commission_type === 'percentage') { // Calculate commission $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100; } else { // Fixed amount $commission = convertToNumber($commission_settings->commission_value); } } else { // No commission $commission = 0; } // Save order item $order_item = new OrderItem(); $order_item->uid = uid(); $order_item->order_id = $order->id; $order_item->gig_id = $gig->id; $order_item->owner_id = $gig->user_id; $order_item->quantity = $quantity; $order_item->has_upgrades = count($upgrades) ? true : false; $order_item->total_value = $item_total; $order_item->profit_value = $item_total - $commission; $order_item->commission_value = $commission; $order_item->save(); // Loop through upgrades again foreach ($upgrades as $index => $value) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Get upgrade $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first(); // Check if upgrade exists if ($upgrade) { // Save item upgrade $order_item_upgrade = new OrderItemUpgrade(); $order_item_upgrade->item_id = $order_item->id; $order_item_upgrade->title = $upgrade->title; $order_item_upgrade->price = $upgrade->price; $order_item_upgrade->extra_days = $upgrade->extra_days; $order_item_upgrade->save(); } } } // Update seller pending balance $gig->owner()->update([ 'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value) ]); // Increment orders in queue $gig->increment('orders_in_queue'); // Order item placed successfully // Let's notify the seller about new order $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) ); // Check user's level check_user_level($buyer_id); // Send notification notification([ 'text' => 't_u_received_new_order_seller', 'action' => url('seller/orders/details', $order_item->uid), 'user_id' => $order_item->owner_id ]); } } // Save invoice $invoice = new OrderInvoice(); $invoice->order_id = $order->id; $invoice->payment_method = $this->gateway; $invoice->payment_id = $payment_id; $invoice->firstname = $billing_info->firstname ?? $user->username; $invoice->lastname = $billing_info->lastname ?? $user->username; $invoice->email = $user->email; $invoice->company = !empty($billing_info->company) ? clean($billing_info->company) : null; $invoice->address = !empty($billing_info->address) ? clean($billing_info->address) : "NA"; $invoice->status = 'paid'; $invoice->save(); // Update balance $user->update([ 'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total) ]); // Now everything succeeded // Let's empty the cart session()->forget('cart'); // Now let's notify the buyer that his order has been placed $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) ); } catch (\Throwable $th) { // Error throw $th; } } /** * Calculate fee value * * @param string $type * @param mixed $amount * @return mixed */ private function fee($type, $amount = null) { try { // Set amount for deposit $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate; // Remove long decimal $amount = convertToNumber( number_format($amount, 2, '.', '') ); // Check fee type switch ($type) { // Deposit case 'deposit': // Get deposit fixed fee if (isset($this->settings->fixed_fee['deposit'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']); } else { // No fixed fee $fee_fixed = 0; } // Get deposit percentage fee if (isset($this->settings->percentage_fee['deposit'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return number_format($fee_value, 2, '.', ''); break; // Gigs case 'gigs': // Get gigs fixed fee if (isset($this->settings->fixed_fee['gigs'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']); } else { // No fixed fee $fee_fixed = 0; } // Get gigs percentage fee if (isset($this->settings->percentage_fee['gigs'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return $fee_value; break; } } catch (\Throwable $th) { // Something went wrong return 0; } } /** * Calculate exchange rate * * @param mixed $amount * @param mixed $exchange_rate * @param boolean $formatted * @param string $currency * @return mixed */ private function exchange($amount, $exchange_rate, $formatted = false, $currency = null) { try { // Convert amount to number $amount = convertToNumber($amount); // Get currency settings $currency_settings = settings('currency'); // Get default currency exchange rate $default_exchange_rate = convertToNumber($currency_settings->exchange_rate); // Get exchanged amount $exchanged_amount = convertToNumber( $amount * $default_exchange_rate / $exchange_rate ); // Check if we have to return a formatted value if ($formatted) { return money( $exchanged_amount, $currency, true )->format(); } // Return max deposit return convertToNumber(number_format( $exchanged_amount, 2, '.', '' )); } catch (\Throwable $th) { // Something went wrong return $amount; } } /** * Send a notification to user * * @param string $type * @param object $user * @return void */ private function notification($type, $user) { try { // Check notification type switch ($type) { // Deposit funds case 'deposit': break; // Gig checkout case 'gig': break; // Project payment case 'project': break; // Bid payment case 'bid': break; } } catch (\Throwable $th) { // Something went wrong return; } } /** * Redirecting * * @param string $type * @param string $status * @return void */ private function redirect($type, $status = 'success') { // Check where to redirect switch ($type) { // Deposit history case 'deposit': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending')); } break; // Gigs order case 'gigs': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending')); } break; } } }
<?php namespace App\Http\Controllers\Callback; use App\Models\Gig; use App\Models\User; use App\Models\Order; use App\Models\OrderItem; use App\Models\GigUpgrade; use App\Models\OrderInvoice; use Illuminate\Http\Request; use App\Models\DepositWebhook; use App\Models\CheckoutWebhook; use App\Models\OrderItemUpgrade; use App\Models\DepositTransaction; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Http; use App\Models\AutomaticPaymentGateway; use App\Notifications\User\Buyer\OrderPlaced; use App\Notifications\User\Seller\PendingOrder; class PaymobPkController extends Controller { public $gateway = "paymob-pk"; public $status = "paid"; public $settings; /** * Payment gateway callback * * @param Request $request * @return mixed */ public function callback(Request $request) { try { // Get payment gateway settings $settings = AutomaticPaymentGateway::where('slug', $this->gateway) ->where('is_active', true) ->firstOrFail(); // Set settings $this->settings = $settings; // Get transaction id $transaction_id = $request->get('id'); // Check webhook event if ( $transaction_id ) { // Check if payment succeeded $response = $this->verify($transaction_id); // Check if payment succeeded if ( is_array($response) && $response['success'] === TRUE) { // Get action $action = $response['response']['obj']['order']['shipping_data']['shipping_method']; // Check if deposit callback if ( isset($action) && $action === "D" ) { // Get saved webhook data in our database $data = DepositWebhook::where('payment_id', $transaction_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Handle deposit callback $this->deposit($data->user_id, $data->amount, $transaction_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('deposit'); } // Check if checkout callback if ( isset($action) && $action === "G" ) { // Get saved webhook data in our database $data = CheckoutWebhook::where('payment_id', $transaction_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Get cart $cart = $data->data['cart']; // Get user $user = User::where('id', $data->data['buyer_id'])->firstOrFail(); // Handle deposit callback $this->checkout($cart, $user, $transaction_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('gigs'); } } } // In case failed redirect to home page return redirect('/'); } catch (\Throwable $th) { // Error throw $th; } } /** * Verify if payment succeeded * * @param string $id * @return array */ private function verify($id) { try { // Get auth token $auth = Http::acceptJson()->post('https://pakistan.paymob.com/api/auth/tokens', [ 'api_key' => $this->settings?->settings['api_key'], ])->json(); // Check if token is set if (isset($auth['token'])) { // Get payment details $payment = Http::withToken($auth['token']) ->get("https://pakistan.paymob.com/api/acceptance/transactions/$id") ->json(); // Check if payment succeeded if ( is_array($payment) && isset($payment['obj']['success']) && $payment['obj']['success'] == true ) { // Done return [ 'success' => true, 'response' => $payment ]; } else { // Failed return [ 'success' => false, 'message' => __('messages.t_error_stripe_payment_failed') ]; } } else { // Failed return [ 'success' => false, 'message' => __('messages.t_error_stripe_payment_failed') ]; } } catch (\Throwable $th) { // Error return [ 'success' => false, 'message' => __('messages.t_toast_something_went_wrong') ]; } } /** * Deposit funds into user's account * * @param int $user_id * @param mixed $amount * @param string $payment_id * @return void */ private function deposit($user_id, $amount, $payment_id) { try { // Set amount $amount = convertToNumber($amount); // Calculate fee from this amount $fee = convertToNumber($this->fee('deposit', $amount)); // Make transaction $deposit = new DepositTransaction(); $deposit->user_id = $user_id; $deposit->transaction_id = $payment_id; $deposit->payment_method = $this->gateway; $deposit->amount_total = $amount; $deposit->amount_fee = $fee; $deposit->amount_net = $amount - $fee; $deposit->currency = $this->settings->currency; $deposit->exchange_rate = $this->settings->exchange_rate; $deposit->status = $this->status; $deposit->ip_address = request()->ip(); $deposit->save(); // Get user $user = User::where('id', $user_id)->firstOrFail(); // Add funds $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net); $user->save(); // Send a notification $this->notification('deposit', $user); } catch (\Throwable $th) { // Error throw $th; } } /** * Checkout * * @param array $cart * @param object $user * @param string $payment_id * @return void */ private function checkout($cart, $user, $payment_id) { try { // Set empty variables $subtotal = 0; $total = 0; $tax = 0; $fee = 0; // Loop through items in cart foreach ($cart as $key => $item) { // Add gig price to subtotal $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']); // Check if item has upgrades $upgrades = $item['upgrades']; // Loop through upgrades if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) { // Loop through upgrades foreach ($upgrades as $j => $upgrade) { // Check if upgrade checked if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Add upgrade price to subtotal $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']); } } } } // Get commission settings $commission_settings = settings('commission'); // Check if taxes enabled if ($commission_settings->enable_taxes) { // Check if type of taxes percentage if ($commission_settings->tax_type === 'percentage') { // Set tax amount $tax = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100); } else { // Set tax amount $tax = convertToNumber($commission_settings->tax_value); } } // Calculate payment gateway fee $fee = convertToNumber($this->fee( 'gigs', $subtotal )); // Calculate total price $total = $subtotal + $tax + $fee; // Get user billing address $billing_info = $user->billing; // Set unique id for this order $uid = uid(); // Get buyer id $buyer_id = $user->id; // Save order $order = new Order(); $order->uid = $uid; $order->buyer_id = $buyer_id; $order->total_value = $total; $order->subtotal_value = $subtotal; $order->taxes_value = $tax; $order->save(); // Loop through items in cart foreach ($cart as $key => $item) { // Get gig $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first(); // Check if gig exists if ($gig) { // Set quantity $quantity = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1; // Set gig upgrades $upgrades = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : []; // Set empty variable $upgrades_amount = 0; // Loop through upgrades foreach ($upgrades as $index => $upgrade) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { $upgrades_amount += convertToNumber($upgrade['price']) * $quantity; } } // Set item total price $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity ); // Calculate commission first if ($commission_settings->commission_from === 'orders') { // Check commission type if ($commission_settings->commission_type === 'percentage') { // Calculate commission $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100; } else { // Fixed amount $commission = convertToNumber($commission_settings->commission_value); } } else { // No commission $commission = 0; } // Save order item $order_item = new OrderItem(); $order_item->uid = uid(); $order_item->order_id = $order->id; $order_item->gig_id = $gig->id; $order_item->owner_id = $gig->user_id; $order_item->quantity = $quantity; $order_item->has_upgrades = count($upgrades) ? true : false; $order_item->total_value = $item_total; $order_item->profit_value = $item_total - $commission; $order_item->commission_value = $commission; $order_item->save(); // Loop through upgrades again foreach ($upgrades as $index => $value) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Get upgrade $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first(); // Check if upgrade exists if ($upgrade) { // Save item upgrade $order_item_upgrade = new OrderItemUpgrade(); $order_item_upgrade->item_id = $order_item->id; $order_item_upgrade->title = $upgrade->title; $order_item_upgrade->price = $upgrade->price; $order_item_upgrade->extra_days = $upgrade->extra_days; $order_item_upgrade->save(); } } } // Update seller pending balance $gig->owner()->update([ 'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value) ]); // Increment orders in queue $gig->increment('orders_in_queue'); // Order item placed successfully // Let's notify the seller about new order $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) ); // Check user's level check_user_level($buyer_id); // Send notification notification([ 'text' => 't_u_received_new_order_seller', 'action' => url('seller/orders/details', $order_item->uid), 'user_id' => $order_item->owner_id ]); } } // Save invoice $invoice = new OrderInvoice(); $invoice->order_id = $order->id; $invoice->payment_method = $this->gateway; $invoice->payment_id = $payment_id; $invoice->firstname = $billing_info->firstname ?? $user->username; $invoice->lastname = $billing_info->lastname ?? $user->username; $invoice->email = $user->email; $invoice->company = !empty($billing_info->company) ? clean($billing_info->company) : null; $invoice->address = !empty($billing_info->address) ? clean($billing_info->address) : "NA"; $invoice->status = 'paid'; $invoice->save(); // Update balance $user->update([ 'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total) ]); // Now everything succeeded // Let's empty the cart session()->forget('cart'); // Now let's notify the buyer that his order has been placed $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) ); } catch (\Throwable $th) { // Error throw $th; } } /** * Calculate fee value * * @param string $type * @param mixed $amount * @return mixed */ private function fee($type, $amount = null) { try { // Set amount for deposit $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate; // Remove long decimal $amount = convertToNumber( number_format($amount, 2, '.', '') ); // Check fee type switch ($type) { // Deposit case 'deposit': // Get deposit fixed fee if (isset($this->settings->fixed_fee['deposit'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']); } else { // No fixed fee $fee_fixed = 0; } // Get deposit percentage fee if (isset($this->settings->percentage_fee['deposit'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return number_format($fee_value, 2, '.', ''); break; // Gigs case 'gigs': // Get gigs fixed fee if (isset($this->settings->fixed_fee['gigs'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']); } else { // No fixed fee $fee_fixed = 0; } // Get gigs percentage fee if (isset($this->settings->percentage_fee['gigs'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return $fee_value; break; } } catch (\Throwable $th) { // Something went wrong return 0; } } /** * Calculate exchange rate * * @param mixed $amount * @param mixed $exchange_rate * @param boolean $formatted * @param string $currency * @return mixed */ private function exchange($amount, $exchange_rate, $formatted = false, $currency = null) { try { // Convert amount to number $amount = convertToNumber($amount); // Get currency settings $currency_settings = settings('currency'); // Get default currency exchange rate $default_exchange_rate = convertToNumber($currency_settings->exchange_rate); // Get exchanged amount $exchanged_amount = convertToNumber( $amount * $default_exchange_rate / $exchange_rate ); // Check if we have to return a formatted value if ($formatted) { return money( $exchanged_amount, $currency, true )->format(); } // Return max deposit return convertToNumber(number_format( $exchanged_amount, 2, '.', '' )); } catch (\Throwable $th) { // Something went wrong return $amount; } } /** * Send a notification to user * * @param string $type * @param object $user * @return void */ private function notification($type, $user) { try { // Check notification type switch ($type) { // Deposit funds case 'deposit': break; // Gig checkout case 'gig': break; // Project payment case 'project': break; // Bid payment case 'bid': break; } } catch (\Throwable $th) { // Something went wrong return; } } /** * Redirecting * * @param string $type * @param string $status * @return void */ private function redirect($type, $status = 'success') { // Check where to redirect switch ($type) { // Deposit history case 'deposit': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending')); } break; // Gigs order case 'gigs': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending')); } break; } } }
<?php namespace App\Http\Controllers\Callback; use App\Models\Gig; use App\Models\User; use App\Models\Order; use App\Models\OrderItem; use App\Models\GigUpgrade; use Illuminate\Support\Str; use App\Models\OrderInvoice; use Illuminate\Http\Request; use App\Models\DepositWebhook; use App\Models\CheckoutWebhook; use App\Models\OrderItemUpgrade; use App\Models\DepositTransaction; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Http; use App\Models\AutomaticPaymentGateway; use App\Notifications\User\Buyer\OrderPlaced; use App\Notifications\User\Seller\PendingOrder; class FlutterwaveController extends Controller { public $gateway = "flutterwave"; public $status = "paid"; public $settings; /** * Payment gateway callback * * @param Request $request * @return mixed */ public function callback(Request $request) { try { // Get payment gateway settings $settings = AutomaticPaymentGateway::where('slug', $this->gateway) ->where('is_active', true) ->firstOrFail(); // Set settings $this->settings = $settings; // Get transaction id $transaction_id = $request->get('transaction_id'); // Check webhook event if ( $transaction_id ) { // Check if payment succeeded $response = $this->verify($transaction_id); // Check if payment succeeded if ( is_array($response) && $response['success'] === TRUE) { // Get order id $order_id = $response['response']['data']['tx_ref']; // Check if deposit callback if (Str::startsWith($order_id, "DD")) { // Get saved webhook data in our database $data = DepositWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Handle deposit callback $this->deposit($data->user_id, $data->amount, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('deposit'); } // Check if checkout callback if (Str::startsWith($order_id, "GG")) { // Get saved webhook data in our database $data = CheckoutWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Get cart $cart = $data->data['cart']; // Get user $user = User::where('id', $data->data['buyer_id'])->firstOrFail(); // Handle deposit callback $this->checkout($cart, $user, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('gigs'); } } } // In case failed redirect to home page return redirect('/'); } catch (\Throwable $th) { // Error throw $th; } } /** * Verify if payment succeeded * * @param string $id * @return array */ private function verify($id) { try { // Get payment gateway keys $secret_key = $this->settings?->settings['secret_key']; $response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $secret_key, 'Accept' => 'application/json', ])->get("https://api.flutterwave.com/v3/transactions/$id/verify")->json(); // Check if payment succeeded if ( is_array($response) && $response['status'] === 'success' ) { // Done return [ 'success' => true, 'response' => $response ]; } else { // Failed return [ 'success' => false, 'message' => __('messages.t_error_stripe_payment_failed') ]; } } catch (\Throwable $th) { // Error return [ 'success' => false, 'message' => __('messages.t_toast_something_went_wrong') ]; } } /** * Deposit funds into user's account * * @param int $user_id * @param mixed $amount * @param string $payment_id * @return void */ private function deposit($user_id, $amount, $payment_id) { try { // Set amount $amount = convertToNumber($amount); // Calculate fee from this amount $fee = convertToNumber($this->fee('deposit', $amount)); // Make transaction $deposit = new DepositTransaction(); $deposit->user_id = $user_id; $deposit->transaction_id = $payment_id; $deposit->payment_method = $this->gateway; $deposit->amount_total = $amount; $deposit->amount_fee = $fee; $deposit->amount_net = $amount - $fee; $deposit->currency = $this->settings->currency; $deposit->exchange_rate = $this->settings->exchange_rate; $deposit->status = $this->status; $deposit->ip_address = request()->ip(); $deposit->save(); // Get user $user = User::where('id', $user_id)->firstOrFail(); // Add funds $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net); $user->save(); // Send a notification $this->notification('deposit', $user); } catch (\Throwable $th) { // Error throw $th; } } /** * Checkout * * @param array $cart * @param object $user * @param string $payment_id * @return void */ private function checkout($cart, $user, $payment_id) { try { // Set empty variables $subtotal = 0; $total = 0; $tax = 0; $fee = 0; // Loop through items in cart foreach ($cart as $key => $item) { // Add gig price to subtotal $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']); // Check if item has upgrades $upgrades = $item['upgrades']; // Loop through upgrades if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) { // Loop through upgrades foreach ($upgrades as $j => $upgrade) { // Check if upgrade checked if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Add upgrade price to subtotal $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']); } } } } // Get commission settings $commission_settings = settings('commission'); // Check if taxes enabled if ($commission_settings->enable_taxes) { // Check if type of taxes percentage if ($commission_settings->tax_type === 'percentage') { // Set tax amount $tax = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100); } else { // Set tax amount $tax = convertToNumber($commission_settings->tax_value); } } // Calculate payment gateway fee $fee = convertToNumber($this->fee( 'gigs', $subtotal )); // Calculate total price $total = $subtotal + $tax + $fee; // Get user billing address $billing_info = $user->billing; // Set unique id for this order $uid = uid(); // Get buyer id $buyer_id = $user->id; // Save order $order = new Order(); $order->uid = $uid; $order->buyer_id = $buyer_id; $order->total_value = $total; $order->subtotal_value = $subtotal; $order->taxes_value = $tax; $order->save(); // Loop through items in cart foreach ($cart as $key => $item) { // Get gig $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first(); // Check if gig exists if ($gig) { // Set quantity $quantity = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1; // Set gig upgrades $upgrades = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : []; // Set empty variable $upgrades_amount = 0; // Loop through upgrades foreach ($upgrades as $index => $upgrade) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { $upgrades_amount += convertToNumber($upgrade['price']) * $quantity; } } // Set item total price $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity ); // Calculate commission first if ($commission_settings->commission_from === 'orders') { // Check commission type if ($commission_settings->commission_type === 'percentage') { // Calculate commission $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100; } else { // Fixed amount $commission = convertToNumber($commission_settings->commission_value); } } else { // No commission $commission = 0; } // Save order item $order_item = new OrderItem(); $order_item->uid = uid(); $order_item->order_id = $order->id; $order_item->gig_id = $gig->id; $order_item->owner_id = $gig->user_id; $order_item->quantity = $quantity; $order_item->has_upgrades = count($upgrades) ? true : false; $order_item->total_value = $item_total; $order_item->profit_value = $item_total - $commission; $order_item->commission_value = $commission; $order_item->save(); // Loop through upgrades again foreach ($upgrades as $index => $value) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Get upgrade $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first(); // Check if upgrade exists if ($upgrade) { // Save item upgrade $order_item_upgrade = new OrderItemUpgrade(); $order_item_upgrade->item_id = $order_item->id; $order_item_upgrade->title = $upgrade->title; $order_item_upgrade->price = $upgrade->price; $order_item_upgrade->extra_days = $upgrade->extra_days; $order_item_upgrade->save(); } } } // Update seller pending balance $gig->owner()->update([ 'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value) ]); // Increment orders in queue $gig->increment('orders_in_queue'); // Order item placed successfully // Let's notify the seller about new order $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) ); // Check user's level check_user_level($buyer_id); // Send notification notification([ 'text' => 't_u_received_new_order_seller', 'action' => url('seller/orders/details', $order_item->uid), 'user_id' => $order_item->owner_id ]); } } // Save invoice $invoice = new OrderInvoice(); $invoice->order_id = $order->id; $invoice->payment_method = $this->gateway; $invoice->payment_id = $payment_id; $invoice->firstname = $billing_info->firstname ?? $user->username; $invoice->lastname = $billing_info->lastname ?? $user->username; $invoice->email = $user->email; $invoice->company = !empty($billing_info->company) ? clean($billing_info->company) : null; $invoice->address = !empty($billing_info->address) ? clean($billing_info->address) : "NA"; $invoice->status = 'paid'; $invoice->save(); // Update balance $user->update([ 'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total) ]); // Now everything succeeded // Let's empty the cart session()->forget('cart'); // Now let's notify the buyer that his order has been placed $user->notify( (new OrderPlaced($order))->locale(config('app.locale')) ); } catch (\Throwable $th) { // Error throw $th; } } /** * Calculate fee value * * @param string $type * @param mixed $amount * @return mixed */ private function fee($type, $amount = null) { try { // Set amount for deposit $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate; // Remove long decimal $amount = convertToNumber( number_format($amount, 2, '.', '') ); // Check fee type switch ($type) { // Deposit case 'deposit': // Get deposit fixed fee if (isset($this->settings->fixed_fee['deposit'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']); } else { // No fixed fee $fee_fixed = 0; } // Get deposit percentage fee if (isset($this->settings->percentage_fee['deposit'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return number_format($fee_value, 2, '.', ''); break; // Gigs case 'gigs': // Get gigs fixed fee if (isset($this->settings->fixed_fee['gigs'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']); } else { // No fixed fee $fee_fixed = 0; } // Get gigs percentage fee if (isset($this->settings->percentage_fee['gigs'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return $fee_value; break; } } catch (\Throwable $th) { // Something went wrong return 0; } } /** * Calculate exchange rate * * @param mixed $amount * @param mixed $exchange_rate * @param boolean $formatted * @param string $currency * @return mixed */ private function exchange($amount, $exchange_rate, $formatted = false, $currency = null) { try { // Convert amount to number $amount = convertToNumber($amount); // Get currency settings $currency_settings = settings('currency'); // Get default currency exchange rate $default_exchange_rate = convertToNumber($currency_settings->exchange_rate); // Get exchanged amount $exchanged_amount = convertToNumber( $amount * $default_exchange_rate / $exchange_rate ); // Check if we have to return a formatted value if ($formatted) { return money( $exchanged_amount, $currency, true )->format(); } // Return max deposit return convertToNumber(number_format( $exchanged_amount, 2, '.', '' )); } catch (\Throwable $th) { // Something went wrong return $amount; } } /** * Send a notification to user * * @param string $type * @param object $user * @return void */ private function notification($type, $user) { try { // Check notification type switch ($type) { // Deposit funds case 'deposit': break; // Gig checkout case 'gig': break; // Project payment case 'project': break; // Bid payment case 'bid': break; } } catch (\Throwable $th) { // Something went wrong return; } } /** * Redirecting * * @param string $type * @param string $status * @return void */ private function redirect($type, $status = 'success') { // Check where to redirect switch ($type) { // Deposit history case 'deposit': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending')); } break; // Gigs order case 'gigs': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending')); } break; } } }
<?php namespace App\Http\Controllers\Callback; use App\Models\Gig; use App\Models\User; use App\Models\Order; use App\Models\OrderItem; use App\Models\GigUpgrade; use Illuminate\Support\Str; use App\Models\OrderInvoice; use Illuminate\Http\Request; use App\Models\DepositWebhook; use App\Models\CheckoutWebhook; use App\Models\OrderItemUpgrade; use App\Models\DepositTransaction; use App\Http\Controllers\Controller; use App\Models\AffiliateTransaction; use App\Models\AffiliateRegisteration; use App\Models\AutomaticPaymentGateway; use App\Notifications\User\Buyer\OrderPlaced; use App\Notifications\User\Seller\PendingOrder; use Srmklive\PayPal\Services\PayPal as PayPalClient; class PaypalController extends Controller { public $gateway = "paypal"; public $status = "paid"; public $settings; /** * Payment gateway callback * * @param Request $request * @return mixed */ public function callback(Request $request) { try { // Get payment gateway settings $settings = AutomaticPaymentGateway::where('slug', $this->gateway) ->where('is_active', true) ->firstOrFail(); // Set settings $this->settings = $settings; // Get transaction id $transaction_id = $request->get('order'); // Check webhook event if ( $transaction_id ) { // Check if payment succeeded $response = $this->verify($transaction_id); // Check if payment succeeded if ( is_array($response) && $response['success'] === TRUE) { // Get order id $order_id = $response['response']['purchase_units'][0]['payments']['captures'][0]['invoice_id']; // Check if deposit callback if (Str::startsWith($order_id, "D-")) { // Get saved webhook data in our database $data = DepositWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Handle deposit callback $this->deposit($data->user_id, $data->amount, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('deposit'); } // Check if checkout callback if (Str::startsWith($order_id, "G-")) { // Get saved webhook data in our database $data = CheckoutWebhook::where('payment_id', $order_id) ->where('payment_method', $this->gateway) ->where('status', 'pending') ->firstOrFail(); // Get cart $cart = $data->data['cart']; // Get user $user = User::where('id', $data->data['buyer_id'])->firstOrFail(); // Handle deposit callback $this->checkout($cart, $user, $order_id); // Delete saved webhook data in our database $data->delete(); // Redirecting return $this->redirect('gigs'); } } } // In case failed redirect to home page return redirect('/'); } catch (\Throwable $th) { // Error throw $th; } } /** * Verify if payment succeeded * * @param string $id * @return array */ private function verify($id) { // Get payment gateway keys $client_id = $this->settings?->settings['client_id']; $client_secret = $this->settings?->settings['client_secret']; $env = $this->settings?->settings['env']; // Set gateway config $config = [ 'mode' => 'sandbox' , 'live' => [ 'client_id' => $client_id, 'client_secret' => $client_secret, 'app_id' => '', ], 'sandbox' => [ 'client_id' => $client_id, 'client_secret' => $client_secret, 'app_id' => '', ], 'payment_action' => 'Sale', 'currency' => $this->settings?->currency, 'notify_url' => 'https://2lancer.ma/paypal/notify', 'locale' => 'en_US', 'validate_ssl' => true, ]; // Set paypal provider and config $client = new PayPalClient(); // Set client credentials $client->setApiCredentials($config); // Get paypal access token $client->getAccessToken(); // Capture this order $order = $client->capturePaymentOrder($id); // Check if payment succeeded if ( is_array($order) && isset($order['status']) && $order['status'] === 'COMPLETED' ) { // Done return [ 'success' => true, 'response' => $order ]; } else { // Failed return [ 'success' => false, 'message' => __('messages.t_error_stripe_payment_failed') ]; } } /** * Deposit funds into user's account * * @param int $user_id * @param mixed $amount * @param string $payment_id * @return void */ private function deposit($user_id, $amount, $payment_id) { try { // Set amount $amount = convertToNumber($amount); // Calculate fee from this amount $fee = convertToNumber($this->fee('deposit', $amount)); // Make transaction $deposit = new DepositTransaction(); $deposit->user_id = $user_id; $deposit->transaction_id = $payment_id; $deposit->payment_method = $this->gateway; $deposit->amount_total = $amount; $deposit->amount_fee = $fee; $deposit->amount_net = $amount - $fee; $deposit->currency = $this->settings->currency; $deposit->exchange_rate = $this->settings->exchange_rate; $deposit->status = $this->status; $deposit->ip_address = request()->ip(); $deposit->save(); // Get user $user = User::where('id', $user_id)->firstOrFail(); // Add funds $user->balance_available = convertToNumber($user->balance_available) + convertToNumber($deposit->amount_net); $user->save(); // Send a notification $this->notification('deposit', $user); } catch (\Throwable $th) { // Error throw $th; } } /** * Checkout * * @param array $cart * @param object $user * @param string $payment_id * @return void */ private function checkout($cart, $user, $payment_id) { try { // Set empty variables $subtotal = 0; $total = 0; $tax = 0; $fee = 0; // Loop through items in cart foreach ($cart as $key => $item) { // Add gig price to subtotal $subtotal += convertToNumber($item['gig']['price']) * convertToNumber($item['quantity']); // Check if item has upgrades $upgrades = $item['upgrades']; // Loop through upgrades if ( isset($upgrades) && is_array($upgrades) && count($upgrades) ) { // Loop through upgrades foreach ($upgrades as $j => $upgrade) { // Check if upgrade checked if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Add upgrade price to subtotal $subtotal += convertToNumber($upgrade['price']) * convertToNumber($item['quantity']); } } } } // Get commission settings $commission_settings = settings('commission'); // Check if taxes enabled if ($commission_settings->enable_taxes) { // Check if type of taxes percentage if ($commission_settings->tax_type === 'percentage') { // Set tax amount $tax = convertToNumber(bcmul($subtotal, $commission_settings->tax_value) / 100); } else { // Set tax amount $tax = convertToNumber($commission_settings->tax_value); } } // Calculate payment gateway fee $fee = convertToNumber($this->fee( 'gigs', $subtotal )); // Calculate total price $total = $subtotal + $tax + $fee; // Get user billing address $billing_info = $user->billing; // Set unique id for this order $uid = uid(); // Get buyer id $buyer_id = $user->id; // Save order $order = new Order(); $order->uid = $uid; $order->buyer_id = $buyer_id; $order->total_value = $total; $order->subtotal_value = $subtotal; $order->taxes_value = $tax; $order->save(); // Loop through items in cart foreach ($cart as $key => $item) { // Get gig $gig = Gig::where('uid', $item['id'])->with('owner')->active()->first(); // Check if gig exists if ($gig) { // Set quantity $quantity = isset($item['quantity']) ? convertToNumber($item['quantity']) : 1; // Set gig upgrades $upgrades = isset($item['upgrades']) && is_array($item['upgrades']) && count($item['upgrades']) ? $item['upgrades'] : []; // Set empty variable $upgrades_amount = 0; // Loop through upgrades foreach ($upgrades as $index => $upgrade) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { $upgrades_amount += convertToNumber($upgrade['price']) * $quantity; } } // Set item total price $item_total = $upgrades_amount + ( convertToNumber($item['gig']['price']) * $quantity ); // Calculate commission first if ($commission_settings->commission_from === 'orders') { // Check commission type if ($commission_settings->commission_type === 'percentage') { // Calculate commission $commission = convertToNumber($commission_settings->commission_value) * $item_total / 100; } else { // Fixed amount $commission = convertToNumber($commission_settings->commission_value); } } else { // No commission $commission = 0; } // Save order item $order_item = new OrderItem(); $order_item->uid = uid(); $order_item->order_id = $order->id; $order_item->gig_id = $gig->id; $order_item->owner_id = $gig->user_id; $order_item->quantity = $quantity; $order_item->has_upgrades = count($upgrades) ? true : false; $order_item->total_value = $item_total; $order_item->profit_value = $item_total - $commission; $order_item->commission_value = $commission; $order_item->save(); // Loop through upgrades again foreach ($upgrades as $index => $value) { // Check if upgrade is selected if ( isset($upgrade['checked']) && $upgrade['checked'] == 1 ) { // Get upgrade $upgrade = GigUpgrade::where('uid', $value['id'])->where('gig_id', $gig->id)->first(); // Check if upgrade exists if ($upgrade) { // Save item upgrade $order_item_upgrade = new OrderItemUpgrade(); $order_item_upgrade->item_id = $order_item->id; $order_item_upgrade->title = $upgrade->title; $order_item_upgrade->price = $upgrade->price; $order_item_upgrade->extra_days = $upgrade->extra_days; $order_item_upgrade->save(); } } } // Update seller pending balance $gig->owner()->update([ 'balance_pending' => convertToNumber($gig->owner->balance_pending) + convertToNumber($order_item->profit_value) ]); // Increment orders in queue $gig->increment('orders_in_queue'); // Order item placed successfully // Let's notify the seller about new order $gig->owner->notify( (new PendingOrder($order_item))->locale(config('app.locale')) ); // Check user's level check_user_level($buyer_id); // Send notification notification([ 'text' => 't_u_received_new_order_seller', 'action' => url('seller/orders/details', $order_item->uid), 'user_id' => $order_item->owner_id ]); } } // Save invoice $invoice = new OrderInvoice(); $invoice->order_id = $order->id; $invoice->payment_method = $this->gateway; $invoice->payment_id = $payment_id; $invoice->firstname = $billing_info->firstname ?? $user->username; $invoice->lastname = $billing_info->lastname ?? $user->username; $invoice->email = $user->email; $invoice->company = !empty($billing_info->company) ? clean($billing_info->company) : null; $invoice->address = !empty($billing_info->address) ? clean($billing_info->address) : "NA"; $invoice->status = 'paid'; $invoice->save(); // Update balance $user->update([ 'balance_purchases' => convertToNumber($user->balance_purchases) + convertToNumber($total) ]); // Now everything succeeded // Let's empty the cart session()->forget('cart'); // Now let's notify the buyer that his order has been placed $user->notify( (new OrderPlaced($order, $total))->locale(config('app.locale')) ); //check for affiliate registeration and check if expired if(settings('affiliate')->is_enabled) { $affiliate_register =AffiliateRegisteration::where('user_id', $buyer_id) ->where('expires_at','>',now()) ->first() ; if($affiliate_register){ // get referral user $referral_user = User::where('id', $affiliate_register->referral_id)->first(); // calculate referral earning $referral_earning =(convertToNumber(settings('affiliate')->profit_percentage)/100)*convertToNumber($total); // add credit to referral wallet $referral_balance = convertToNumber($referral_user->balance_available) + $referral_earning; $referral_user->update(['balance_available'=>$referral_balance]); // create new affiliate transaction $affiliate_transaction = new AffiliateTransaction(); $affiliate_transaction->user_id = $buyer_id ; $affiliate_transaction->referral_id = $referral_user->id ; $affiliate_transaction->order_id = $order->id ; $affiliate_transaction->referral_earning = $referral_earning ; $affiliate_transaction->save(); } } } catch (\Throwable $th) { // Error throw $th; } } /** * Calculate fee value * * @param string $type * @param mixed $amount * @return mixed */ private function fee($type, $amount = null) { try { // Set amount for deposit $amount = convertToNumber($amount) * $this->settings?->exchange_rate / settings('currency')->exchange_rate; // Remove long decimal $amount = convertToNumber( number_format($amount, 2, '.', '') ); // Check fee type switch ($type) { // Deposit case 'deposit': // Get deposit fixed fee if (isset($this->settings->fixed_fee['deposit'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['deposit']); } else { // No fixed fee $fee_fixed = 0; } // Get deposit percentage fee if (isset($this->settings->percentage_fee['deposit'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['deposit']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return number_format($fee_value, 2, '.', ''); break; // Gigs case 'gigs': // Get gigs fixed fee if (isset($this->settings->fixed_fee['gigs'])) { // Set fixed fee $fee_fixed = convertToNumber($this->settings->fixed_fee['gigs']); } else { // No fixed fee $fee_fixed = 0; } // Get gigs percentage fee if (isset($this->settings->percentage_fee['gigs'])) { // Set percentage fee $fee_percentage = convertToNumber($this->settings->percentage_fee['gigs']); } else { // No percentage fee $fee_percentage = 0; } // Calculate percentage of this amount $fee_percentage_amount = $this->exchange( $fee_percentage * $amount / 100, $this->settings->exchange_rate ); // Calculate exchange rate of this fixed fee $fee_fixed_exchange = $this->exchange( $fee_fixed, $this->settings->exchange_rate); // Calculate fee value and visible text if ($fee_fixed > 0 && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount) + convertToNumber($fee_fixed_exchange); } else if (!$fee_fixed && $fee_percentage > 0) { // Calculate fee value $fee_value = convertToNumber($fee_percentage_amount); } else if ($fee_fixed > 0 && !$fee_percentage) { // Calculate fee value $fee_value = convertToNumber($fee_fixed_exchange); } else if (!$fee_percentage && !$fee_fixed) { // Calculate fee value $fee_value = 0; } // Return fee value return $fee_value; break; } } catch (\Throwable $th) { // Something went wrong return 0; } } /** * Calculate exchange rate * * @param mixed $amount * @param mixed $exchange_rate * @param boolean $formatted * @param string $currency * @return mixed */ private function exchange($amount, $exchange_rate, $formatted = false, $currency = null) { try { // Convert amount to number $amount = convertToNumber($amount); // Get currency settings $currency_settings = settings('currency'); // Get default currency exchange rate $default_exchange_rate = convertToNumber($currency_settings->exchange_rate); // Get exchanged amount $exchanged_amount = convertToNumber( $amount * $default_exchange_rate / $exchange_rate ); // Check if we have to return a formatted value if ($formatted) { return money( $exchanged_amount, $currency, true )->format(); } // Return max deposit return convertToNumber(number_format( $exchanged_amount, 2, '.', '' )); } catch (\Throwable $th) { // Something went wrong return $amount; } } /** * Send a notification to user * * @param string $type * @param object $user * @return void */ private function notification($type, $user) { try { // Check notification type switch ($type) { // Deposit funds case 'deposit': break; // Gig checkout case 'gig': break; // Project payment case 'project': break; // Bid payment case 'bid': break; } } catch (\Throwable $th) { // Something went wrong return; } } /** * Redirecting * * @param string $type * @param string $status * @return void */ private function redirect($type, $status = 'success') { // Check where to redirect switch ($type) { // Deposit history case 'deposit': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_ur_transaction_has_completed')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/deposit/history')->with('success', __('messages.t_mollie_payment_pending')); } break; // Gigs order case 'gigs': // Check if payment succeeded if ($status === 'success') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_submit_ur_info_now_seller_start_order')); } else if ($status === 'pending') { // Redirect to deposit history page return redirect('account/orders')->with('success', __('messages.t_mollie_payment_pending')); } break; } } }