HTTP status codes
Mon Jun 28 2021 15:52:32 GMT+0000 (Coordinated Universal Time)
Mon Jun 28 2021 15:52:32 GMT+0000 (Coordinated Universal Time)
HTTP defines a bunch of meaningful status codes that can be returned from your API. These can be leveraged to help the API consumers route their responses accordingly. I've curated a short list of the ones that you definitely should be using: 200 OK - Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn't result in a creation. 201 Created - Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource 204 No Content - Response to a successful request that won't be returning a body (like a DELETE request) 304 Not Modified - Used when HTTP caching headers are in play 400 Bad Request - The request is malformed, such as if the body does not parse 401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser 403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource 404 Not Found - When a non-existent resource is requested 405 Method Not Allowed - When an HTTP method is being requested that isn't allowed for the authenticated user 410 Gone - Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions 415 Unsupported Media Type - If incorrect content type was provided as part of the request 422 Unprocessable Entity - Used for validation errors 429 Too Many Requests - When a request is rejected due to rate limiting
const getURLParameters = url =>
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
(a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
{}
);
// Examples
getURLParameters('http://url.com/page?n=Adam&s=Smith'); // {n: 'Adam', s: 'Smith'}
getURLParameters('google.com'); // {}
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</IfModule>
Options +Indexes IndexOptions FancyIndexing IndexIgnore README .htaccess
HTTP defines a bunch of meaningful status codes that can be returned from your API. These can be leveraged to help the API consumers route their responses accordingly. I've curated a short list of the ones that you definitely should be using: 200 OK - Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn't result in a creation. 201 Created - Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource 204 No Content - Response to a successful request that won't be returning a body (like a DELETE request) 304 Not Modified - Used when HTTP caching headers are in play 400 Bad Request - The request is malformed, such as if the body does not parse 401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser 403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource 404 Not Found - When a non-existent resource is requested 405 Method Not Allowed - When an HTTP method is being requested that isn't allowed for the authenticated user 410 Gone - Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions 415 Unsupported Media Type - If incorrect content type was provided as part of the request 422 Unprocessable Entity - Used for validation errors 429 Too Many Requests - When a request is rejected due to rate limiting
var open = window.XMLHttpRequest.prototype.open,
send = window.XMLHttpRequest.prototype.send;
function openReplacement(method, url, async, user, password) {
this._url = url;
return open.apply(this, arguments);
}
function sendReplacement(data) {
if(this.onreadystatechange) {
this._onreadystatechange = this.onreadystatechange;
}
/**
* PLACE HERE YOUR CODE WHEN REQUEST IS SENT
*/
this.onreadystatechange = onReadyStateChangeReplacement;
return send.apply(this, arguments);
}
function onReadyStateChangeReplacement() {
/**
* PLACE HERE YOUR CODE FOR READYSTATECHANGE
*/
if(this._onreadystatechange) {
return this._onreadystatechange.apply(this, arguments);
}
}
window.XMLHttpRequest.prototype.open = openReplacement;
window.XMLHttpRequest.prototype.send = sendReplacement;
// https://dmitripavlutin.com/catch-the-xmlhttp-request-in-plain-javascript/
httpClient() {
curl --silent \
# everything in between
--write-out "\n%{http_code}"
}
response=`httpClient #args #args .....`
http_code=`tail -n1 <<< "$response"`
body=`sed '$ d' <<< "$response"`
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService<T> {
final String _baseUrl;
ApiService(this._baseUrl);
Future<List<T>> getAll(T Function(Map<String, dynamic>) fromJson) async {
final response = await http.get(Uri.parse(_baseUrl));
if (response.statusCode == 200) {
final jsonData = json.decode(response.body) as List;
return jsonData.map((data) => fromJson(data)).toList();
} else {
throw Exception('Failed to load data');
}
}
Future<List<T>> search(String query, T Function(Map<String, dynamic>) fromJson) async {
final response = await http.get(Uri.parse('$_baseUrl?search=$query'));
if (response.statusCode == 200) {
final jsonData = json.decode(response.body) as List;
return jsonData.map((data) => fromJson(data)).toList();
} else {
throw Exception('Failed to search data');
}
}
Future<T> create(Map<String, dynamic> data, T Function(Map<String, dynamic>) fromJson) async {
final response = await http.post(
Uri.parse(_baseUrl),
headers: {'Content-Type': 'application/json'},
body: json.encode(data),
);
if (response.statusCode == 201) {
return fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create data');
}
}
Future<T> update(int id, Map<String, dynamic> data, T Function(Map<String, dynamic>) fromJson) async {
final response = await http.put(
Uri.parse('$_baseUrl/$id'),
headers: {'Content-Type': 'application/json'},
body: json.encode(data),
);
if (response.statusCode == 200) {
return fromJson(json.decode(response.body));
} else {
throw Exception('Failed to update data');
}
}
Future<void> delete(int id) async {
final response = await http.delete(Uri.parse('$_baseUrl/$id'));
if (response.statusCode != 204) {
throw Exception('Failed to delete data');
}
}
}
//=============================================
class Note {
final int id;
final String title;
final String content;
Note({required this.id, required this.title, required this.content});
factory Note.fromJson(Map<String, dynamic> json) {
return Note(
id: json['id'],
title: json['title'],
content: json['content'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'content': content,
};
}
}
final notesService = ApiService<Note>('http://10.0.2.2:8000/api/notes');
// Get all notes
final notes = await notesService.getAll(Note.fromJson);
// Search for notes
final searchResults = await notesService.search('keyword', Note.fromJson);
// Create a new note
final newNote = await notesService.create(
{
'title': 'New Note',
'content': 'This is a new note',
},
Note.fromJson,
);
// Update a note
final updatedNote = await notesService.update(
newNote.id,
{
'title': 'Updated Note',
'content': 'This is an updated note',
},
Note.fromJson,
);
// Delete a note
await notesService.delete(updatedNote.id);
import 'package:flutter/material.dart';
import 'package:shalestin/Screens/home.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'Home': (context) => const Home(),
},
initialRoute: 'Home',
debugShowCheckedModeBanner: false,
);
}
}
<?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;
}
}
}
<?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 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 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;
}
}
}
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
// تأكد من تثبيت مكتبة 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>



Comments