Merge branch 'development' into servers-servercard

This commit is contained in:
IceToast 2021-12-22 15:14:21 +01:00
commit 2bfe26247a
30 changed files with 2344 additions and 1379 deletions

View file

@ -1,4 +1,4 @@
APP_NAME=Dashboard
APP_NAME=Controlpanel.gg
APP_ENV=production
APP_KEY=
APP_DEBUG=false
@ -25,6 +25,18 @@ PAYPAL_SECRET=
PAYPAL_CLIENT_ID=
PAYPAL_EMAIL=
#stripe details, you only need "test" for testing! you can do this by setting the APP_ENV to local
STRIPE_TEST_SECRET=
STRIPE_SECRET=
#https://dashboard.stripe.com/webhooks -> webhook route: <your.controlpanel.gg>/payment/StripeWebhooks
STRIPE_ENDPOINT_TEST_SECRET=
STRIPE_ENDPOINT_SECRET=
#stripe payment methods, comma seperated list of methods you want to support:
#read into https://stripe.com/docs/payments/payment-methods/integration-options and/or https://stripe.com/docs/payments/payment-methods/overview
#Method needs to support the currency
STRIPE_METHODS=
#set-up for extra discord verification
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=

View file

@ -1,25 +1,32 @@
### Features
- PayPal Integration
- Email Verification
- Audit Log
- Admin Dashboard
- User/Server Management
- Store (credit system)
- Vouchers
- and so much more!
- PayPal Integration
- Stripe Integration
- Email Verification
- Audit Log
- Admin Dashboard
- User/Server Management
- Store (credit system)
- Vouchers
- and so much more!
# ControlPanel-gg
![controlpanel](https://user-images.githubusercontent.com/45005889/123518824-06b05000-d6a8-11eb-91b9-d1ed36bd2317.png)
![](https://img.shields.io/github/stars/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/forks/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/tag/ControlPanel-gg/dashboard) [![Crowdin](https://badges.crowdin.net/controlpanelgg/localized.svg)](https://crowdin.com/project/controlpanelgg) ![](https://img.shields.io/github/issues/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/license/ControlPanel-gg/dashboard) ![](https://img.shields.io/discord/787829714483019826)
## About
ControlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits.
This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customization options and added discord 0auth verification to offer a solid link between your discord server and your dashboard.
### [Installation](https://controlpanel.gg/docs/intro "Installation")
### [Updating](https://controlpanel.gg/docs/Installation/updating "Updating")
### [Discord](https://discord.gg/4Y6HjD2uyU "discord")
### [Contributing](https://controlpanel.gg/docs/Contributing/contributing "Contributing")
### [Donating](https://controlpanel.gg/docs/Contributing/donating "Donating")

View file

@ -2,7 +2,7 @@
namespace App\Http\Controllers\Admin;
use App\Models\PaypalProduct;
use App\Models\CreditProduct;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
@ -12,7 +12,7 @@ use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use Illuminate\Validation\Rule;
class PaypalProductController extends Controller
class CreditProductController extends Controller
{
/**
* Display a listing of the resource.
@ -21,11 +21,16 @@ class PaypalProductController extends Controller
*/
public function index(Request $request)
{
$isPaypalSetup = false;
if (env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID')) $isPaypalSetup = true;
$isPaymentSetup = false;
return view('admin.store.index' , [
'isPaypalSetup' => $isPaypalSetup
if (
env('APP_ENV') == 'local' ||
env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID') ||
env('STRIPE_SECRET') && env('STRIPE_ENDPOINT_SECRET') && env('STRIPE_METHODS')
) $isPaymentSetup = true;
return view('admin.store.index', [
'isPaymentSetup' => $isPaymentSetup
]);
}
@ -60,7 +65,7 @@ class PaypalProductController extends Controller
]);
$disabled = !is_null($request->input('disabled'));
PaypalProduct::create(array_merge($request->all(), ['disabled' => $disabled]));
CreditProduct::create(array_merge($request->all(), ['disabled' => $disabled]));
return redirect()->route('admin.store.index')->with('success', __('Store item has been created!'));
}
@ -68,10 +73,10 @@ class PaypalProductController extends Controller
/**
* Display the specified resource.
*
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return Response
*/
public function show(PaypalProduct $paypalProduct)
public function show(CreditProduct $creditProduct)
{
//
}
@ -79,14 +84,14 @@ class PaypalProductController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return Application|Factory|View|Response
*/
public function edit(PaypalProduct $paypalProduct)
public function edit(CreditProduct $creditProduct)
{
return view('admin.store.edit', [
'currencyCodes' => config('currency_codes'),
'paypalProduct' => $paypalProduct
'creditProduct' => $creditProduct
]);
}
@ -94,10 +99,10 @@ class PaypalProductController extends Controller
* Update the specified resource in storage.
*
* @param Request $request
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return RedirectResponse
*/
public function update(Request $request, PaypalProduct $paypalProduct)
public function update(Request $request, CreditProduct $creditProduct)
{
$request->validate([
"disabled" => "nullable",
@ -110,19 +115,19 @@ class PaypalProductController extends Controller
]);
$disabled = !is_null($request->input('disabled'));
$paypalProduct->update(array_merge($request->all(), ['disabled' => $disabled]));
$creditProduct->update(array_merge($request->all(), ['disabled' => $disabled]));
return redirect()->route('admin.store.index')->with('success', __('Store item has been updated!'));
}
/**
* @param Request $request
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return RedirectResponse
*/
public function disable(Request $request, PaypalProduct $paypalProduct)
public function disable(Request $request, CreditProduct $creditProduct)
{
$paypalProduct->update(['disabled' => !$paypalProduct->disabled]);
$creditProduct->update(['disabled' => !$creditProduct->disabled]);
return redirect()->route('admin.store.index')->with('success', __('Product has been updated!'));
}
@ -130,50 +135,50 @@ class PaypalProductController extends Controller
/**
* Remove the specified resource from storage.
*
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return RedirectResponse
*/
public function destroy(PaypalProduct $paypalProduct)
public function destroy(CreditProduct $creditProduct)
{
$paypalProduct->delete();
$creditProduct->delete();
return redirect()->back()->with('success', __('Store item has been removed!'));
}
public function dataTable()
{
$query = PaypalProduct::query();
$query = CreditProduct::query();
return datatables($query)
->addColumn('actions', function (PaypalProduct $paypalProduct) {
->addColumn('actions', function (CreditProduct $creditProduct) {
return '
<a data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.store.edit', $paypalProduct->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
<a data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.store.edit', $creditProduct->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.destroy', $paypalProduct->id) . '">
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.destroy', $creditProduct->id) . '">
' . csrf_field() . '
' . method_field("DELETE") . '
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
<button data-content="' . __("Delete") . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
</form>
';
})
->addColumn('disabled', function (PaypalProduct $paypalProduct) {
$checked = $paypalProduct->disabled == false ? "checked" : "";
->addColumn('disabled', function (CreditProduct $creditProduct) {
$checked = $creditProduct->disabled == false ? "checked" : "";
return '
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.disable', $paypalProduct->id) . '">
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.disable', $creditProduct->id) . '">
' . csrf_field() . '
' . method_field("PATCH") . '
<div class="custom-control custom-switch">
<input ' . $checked . ' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch' . $paypalProduct->id . '">
<label class="custom-control-label" for="switch' . $paypalProduct->id . '"></label>
<input ' . $checked . ' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch' . $creditProduct->id . '">
<label class="custom-control-label" for="switch' . $creditProduct->id . '"></label>
</div>
</form>
';
})
->editColumn('created_at', function (PaypalProduct $paypalProduct) {
return $paypalProduct->created_at ? $paypalProduct->created_at->diffForHumans() : '';
->editColumn('created_at', function (CreditProduct $creditProduct) {
return $creditProduct->created_at ? $creditProduct->created_at->diffForHumans() : '';
})
->editColumn('price', function (PaypalProduct $paypalProduct) {
return $paypalProduct->formatToCurrency($paypalProduct->price);
->editColumn('price', function (CreditProduct $creditProduct) {
return $creditProduct->formatToCurrency($creditProduct->price);
})
->rawColumns(['actions', 'disabled'])
->make();

View file

@ -7,9 +7,10 @@ use App\Http\Controllers\Controller;
use App\Models\Configuration;
use App\Models\InvoiceSettings;
use App\Models\Payment;
use App\Models\PaypalProduct;
use App\Models\CreditProduct;
use App\Models\User;
use App\Notifications\InvoiceNotification;
use App\Notifications\ConfirmPaymentNotification;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
@ -29,6 +30,8 @@ use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalHttp\HttpException;
use Stripe\Stripe;
class PaymentController extends Controller
{
@ -45,25 +48,25 @@ class PaymentController extends Controller
/**
* @param Request $request
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return Application|Factory|View
*/
public function checkOut(Request $request, PaypalProduct $paypalProduct)
public function checkOut(Request $request, CreditProduct $creditProduct)
{
return view('store.checkout')->with([
'product' => $paypalProduct,
'taxvalue' => $paypalProduct->getTaxValue(),
'taxpercent' => $paypalProduct->getTaxPercent(),
'total' => $paypalProduct->getTotalPrice()
'product' => $creditProduct,
'taxvalue' => $creditProduct->getTaxValue(),
'taxpercent' => $creditProduct->getTaxPercent(),
'total' => $creditProduct->getTotalPrice()
]);
}
/**
* @param Request $request
* @param PaypalProduct $paypalProduct
* @param CreditProduct $creditProduct
* @return RedirectResponse
*/
public function pay(Request $request, PaypalProduct $paypalProduct)
public function PaypalPay(Request $request, CreditProduct $creditProduct)
{
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
@ -72,30 +75,30 @@ class PaymentController extends Controller
"purchase_units" => [
[
"reference_id" => uniqid(),
"description" => $paypalProduct->description,
"amount" => [
"value" => $paypalProduct->getTotalPrice(),
'currency_code' => strtoupper($paypalProduct->currency_code),
"description" => $creditProduct->description,
"amount" => [
"value" => $creditProduct->getTotalPrice(),
'currency_code' => strtoupper($creditProduct->currency_code),
'breakdown' => [
'item_total' =>
[
'currency_code' => strtoupper($paypalProduct->currency_code),
'value' => $paypalProduct->price,
],
[
'currency_code' => strtoupper($creditProduct->currency_code),
'value' => $creditProduct->price,
],
'tax_total' =>
[
'currency_code' => strtoupper($paypalProduct->currency_code),
'value' => $paypalProduct->getTaxValue(),
]
[
'currency_code' => strtoupper($creditProduct->currency_code),
'value' => $creditProduct->getTaxValue(),
]
]
]
]
],
"application_context" => [
"cancel_url" => route('payment.cancel'),
"return_url" => route('payment.success', ['product' => $paypalProduct->id]),
'brand_name' => config('app.name', 'Laravel'),
'shipping_preference' => 'NO_SHIPPING'
"cancel_url" => route('payment.Cancel'),
"return_url" => route('payment.PaypalSuccess', ['product' => $creditProduct->id]),
'brand_name' => config('app.name', 'Laravel'),
'shipping_preference' => 'NO_SHIPPING'
]
@ -112,7 +115,6 @@ class PaymentController extends Controller
echo $ex->statusCode;
dd(json_decode($ex->getMessage()));
}
}
/**
@ -121,8 +123,8 @@ class PaymentController extends Controller
protected function getPayPalClient()
{
$environment = env('APP_ENV') == 'local'
? new SandboxEnvironment($this->getClientId(), $this->getClientSecret())
: new ProductionEnvironment($this->getClientId(), $this->getClientSecret());
? new SandboxEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret())
: new ProductionEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret());
return new PayPalHttpClient($environment);
}
@ -130,7 +132,7 @@ class PaymentController extends Controller
/**
* @return string
*/
protected function getClientId()
protected function getPaypalClientId()
{
return env('APP_ENV') == 'local' ? env('PAYPAL_SANDBOX_CLIENT_ID') : env('PAYPAL_CLIENT_ID');
}
@ -138,7 +140,7 @@ class PaymentController extends Controller
/**
* @return string
*/
protected function getClientSecret()
protected function getPaypalClientSecret()
{
return env('APP_ENV') == 'local' ? env('PAYPAL_SANDBOX_SECRET') : env('PAYPAL_SECRET');
}
@ -146,10 +148,11 @@ class PaymentController extends Controller
/**
* @param Request $laravelRequest
*/
public function success(Request $laravelRequest)
public function PaypalSuccess(Request $laravelRequest)
{
/** @var PaypalProduct $paypalProduct */
$paypalProduct = PaypalProduct::findOrFail($laravelRequest->input('product'));
/** @var CreditProduct $creditProduct */
$creditProduct = CreditProduct::findOrFail($laravelRequest->input('product'));
/** @var User $user */
$user = Auth::user();
@ -161,7 +164,7 @@ class PaymentController extends Controller
if ($response->statusCode == 201 || $response->statusCode == 200) {
//update credits
$user->increment('credits', $paypalProduct->quantity);
$user->increment('credits', $creditProduct->quantity);
//update server limit
if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
@ -179,82 +182,22 @@ class PaymentController extends Controller
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => $response->result->id,
'payer_id' => $laravelRequest->input('PayerID'),
'payment_method' => 'paypal',
'type' => 'Credits',
'status' => $response->result->status,
'amount' => $paypalProduct->quantity,
'price' => $paypalProduct->price,
'tax_value' => $paypalProduct->getTaxValue(),
'tax_percent' => $paypalProduct->getTaxPercent(),
'total_price' => $paypalProduct->getTotalPrice(),
'currency_code' => $paypalProduct->currency_code,
'payer' => json_encode($response->result->payer),
'status' => 'paid',
'amount' => $creditProduct->quantity,
'price' => $creditProduct->price,
'tax_value' => $creditProduct->getTaxValue(),
'tax_percent' => $creditProduct->getTaxPercent(),
'total_price' => $creditProduct->getTotalPrice(),
'currency_code' => $creditProduct->currency_code,
'credit_product_id' => $creditProduct->id,
]);
event(new UserUpdateCreditsEvent($user));
//create invoice
$lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
$newInvoiceID = $lastInvoiceID + 1;
$InvoiceSettings = InvoiceSettings::query()->first();
$logoPath = storage_path('app/public/logo.png');
$seller = new Party([
'name' => $InvoiceSettings->company_name,
'phone' => $InvoiceSettings->company_phone,
'address' => $InvoiceSettings->company_adress,
'vat' => $InvoiceSettings->company_vat,
'custom_fields' => [
'E-Mail' => $InvoiceSettings->company_mail,
"Web" => $InvoiceSettings->company_web
],
]);
$customer = new Buyer([
'name' => $user->name,
'custom_fields' => [
'E-Mail' => $user->email,
'Client ID' => $user->id,
],
]);
$item = (new InvoiceItem())
->title($paypalProduct->description)
->pricePerUnit($paypalProduct->price);
$invoice = Invoice::make()
->template('controlpanel')
->name(__("Invoice"))
->buyer($customer)
->seller($seller)
->discountByPercent(0)
->taxRate(floatval($paypalProduct->getTaxPercent()))
->shipping(0)
->addItem($item)
->status(__('Paid'))
->series(now()->format('mY'))
->delimiter("-")
->sequence($newInvoiceID)
->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}');
if (file_exists($logoPath)) {
$invoice->logo($logoPath);
}
//Save the invoice in "storage\app\invoice\USER_ID\YEAR"
$invoice->filename = $invoice->getSerialNumber() . '.pdf';
$invoice->render();
Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
\App\Models\Invoice::create([
'invoice_user' => $user->id,
'invoice_name' => $invoice->getSerialNumber(),
'payment_id' => $payment->payment_id,
]);
//Send Invoice per Mail
$user->notify(new InvoiceNotification($invoice, $user, $payment));
$this->createInvoice($user, $payment, 'paid');
//redirect back to home
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
@ -267,7 +210,6 @@ class PaymentController extends Controller
} else {
abort(500);
}
} catch (HttpException $ex) {
if (env('APP_ENV') == 'local') {
echo $ex->statusCode;
@ -275,20 +217,351 @@ class PaymentController extends Controller
} else {
abort(422);
}
}
}
/**
* @param Request $request
*/
public function cancel(Request $request)
public function Cancel(Request $request)
{
return redirect()->route('store.index')->with('success', __('Payment was Canceled'));
return redirect()->route('store.index')->with('success', 'Payment was Canceled');
}
/**
* @param Request $request
* @param CreditProduct $creditProduct
* @return RedirectResponse
*/
public function StripePay(Request $request, CreditProduct $creditProduct)
{
$stripeClient = $this->getStripeClient();
$request = $stripeClient->checkout->sessions->create([
'line_items' => [
[
'price_data' => [
'currency' => $creditProduct->currency_code,
'product_data' => [
'name' => $creditProduct->display,
'description' => $creditProduct->description,
],
'unit_amount_decimal' => round($creditProduct->price * 100, 2),
],
'quantity' => 1,
],
[
'price_data' => [
'currency' => $creditProduct->currency_code,
'product_data' => [
'name' => 'Product Tax',
'description' => $creditProduct->getTaxPercent() . "%",
],
'unit_amount_decimal' => round($creditProduct->getTaxValue(), 2) * 100,
],
'quantity' => 1,
]
],
'mode' => 'payment',
"payment_method_types" => str_getcsv(env('STRIPE_METHODS')),
'success_url' => route('payment.StripeSuccess', ['product' => $creditProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('payment.Cancel'),
]);
return redirect($request->url, 303);
}
/**
* @param Request $request
*/
public function StripeSuccess(Request $request)
{
/** @var CreditProduct $creditProduct */
$creditProduct = CreditProduct::findOrFail($request->input('product'));
/** @var User $user */
$user = Auth::user();
$stripeClient = $this->getStripeClient();
try {
//get stripe data
$paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
$paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
//get DB entry of this payment ID if existing
$paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
// check if payment is 100% completed and payment does not exist in db already
if ($paymentSession->status == "complete" && $paymentIntent->status == "succeeded" && $paymentDbEntry == 0) {
//update credits
$user->increment('credits', $creditProduct->quantity);
//update server limit
if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
$user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
}
}
//update role
if ($user->role == 'member') {
$user->update(['role' => 'client']);
}
//store paid payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => $paymentSession->payment_intent,
'payment_method' => 'stripe',
'type' => 'Credits',
'status' => 'paid',
'amount' => $creditProduct->quantity,
'price' => $creditProduct->price,
'tax_value' => $creditProduct->getTaxValue(),
'total_price' => $creditProduct->getTotalPrice(),
'tax_percent' => $creditProduct->getTaxPercent(),
'currency_code' => $creditProduct->currency_code,
'credit_product_id' => $creditProduct->id,
]);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
$this->createInvoice($user, $payment, 'paid');
//redirect back to home
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
} else {
if ($paymentIntent->status == "processing") {
//store processing payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => $paymentSession->payment_intent,
'payment_method' => 'stripe',
'type' => 'Credits',
'status' => 'processing',
'amount' => $creditProduct->quantity,
'price' => $creditProduct->price,
'tax_value' => $creditProduct->getTaxValue(),
'total_price' => $creditProduct->getTotalPrice(),
'tax_percent' => $creditProduct->getTaxPercent(),
'currency_code' => $creditProduct->currency_code,
'credit_product_id' => $creditProduct->id,
]);
$this->createInvoice($user, $payment, 'processing');
//redirect back to home
return redirect()->route('home')->with('success', __('Your payment is being processed!'));
}
if ($paymentDbEntry == 0 && $paymentIntent->status != "processing") {
$stripeClient->paymentIntents->cancel($paymentIntent->id);
//redirect back to home
return redirect()->route('home')->with('success', __('Your payment has been canceled!'));
} else {
abort(402);
}
}
} catch (HttpException $ex) {
if (env('APP_ENV') == 'local') {
echo $ex->statusCode;
dd($ex->getMessage());
} else {
abort(422);
}
}
}
/**
* @param Request $request
*/
protected function handleStripePaymentSuccessHook($paymentIntent)
{
try {
// Get payment db entry
$payment = Payment::where('payment_id', $paymentIntent->id)->first();
$user = User::where('id', $payment->user_id)->first();
if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
// Increment User Credits
$user->increment('credits', $payment->amount);
//update server limit
if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
$user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
}
}
//update role
if ($user->role == 'member') {
$user->update(['role' => 'client']);
}
//update payment db entry status
$payment->update(['status' => 'paid']);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
$this->createInvoice($user, $payment, 'paid');
}
} catch (HttpException $ex) {
abort(422);
}
}
/**
* @param Request $request
*/
public function StripeWebhooks(Request $request)
{
\Stripe\Stripe::setApiKey($this->getStripeSecret());
try {
$payload = @file_get_contents('php://input');
$sig_header = $request->header('Stripe-Signature');
$event = null;
$event = \Stripe\Webhook::constructEvent(
$payload,
$sig_header,
$this->getStripeEndpointSecret()
);
} catch (\UnexpectedValueException $e) {
// Invalid payload
abort(400);
} catch (\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
abort(400);
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
$this->handleStripePaymentSuccessHook($paymentIntent);
break;
default:
echo 'Received unknown event type ' . $event->type;
}
}
/**
* @return \Stripe\StripeClient
*/
protected function getStripeClient()
{
return new \Stripe\StripeClient($this->getStripeSecret());
}
/**
* @return string
*/
protected function getStripeSecret()
{
return env('APP_ENV') == 'local'
? env('STRIPE_TEST_SECRET')
: env('STRIPE_SECRET');
}
/**
* @return string
*/
protected function getStripeEndpointSecret()
{
return env('APP_ENV') == 'local'
? env('STRIPE_ENDPOINT_TEST_SECRET')
: env('STRIPE_ENDPOINT_SECRET');
}
protected function createInvoice($user, $payment, $paymentStatus)
{
$creditProduct = CreditProduct::where('id', $payment->credit_product_id)->first();
//create invoice
$lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
$newInvoiceID = $lastInvoiceID + 1;
$InvoiceSettings = InvoiceSettings::query()->first();
$logoPath = storage_path('app/public/logo.png');
$seller = new Party([
'name' => $InvoiceSettings->company_name,
'phone' => $InvoiceSettings->company_phone,
'address' => $InvoiceSettings->company_adress,
'vat' => $InvoiceSettings->company_vat,
'custom_fields' => [
'E-Mail' => $InvoiceSettings->company_mail,
"Web" => $InvoiceSettings->company_web
],
]);
$customer = new Buyer([
'name' => $user->name,
'custom_fields' => [
'E-Mail' => $user->email,
'Client ID' => $user->id,
],
]);
$item = (new InvoiceItem())
->title($creditProduct->description)
->pricePerUnit($creditProduct->price);
$notes = [
__("Payment method") .": ". $payment->payment_method,
];
$notes = implode("<br>", $notes);
$invoice = Invoice::make()
->template('controlpanel')
->name(__("Invoice"))
->buyer($customer)
->seller($seller)
->discountByPercent(0)
->taxRate(floatval($creditProduct->getTaxPercent()))
->shipping(0)
->addItem($item)
->status(__($paymentStatus))
->series(now()->format('mY'))
->delimiter("-")
->sequence($newInvoiceID)
->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}')
->notes($notes);
if (file_exists($logoPath)) {
$invoice->logo($logoPath);
}
//Save the invoice in "storage\app\invoice\USER_ID\YEAR"
$invoice->filename = $invoice->getSerialNumber() . '.pdf';
$invoice->render();
Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
\App\Models\Invoice::create([
'invoice_user' => $user->id,
'invoice_name' => $invoice->getSerialNumber(),
'payment_id' => $payment->payment_id,
]);
//Send Invoice per Mail
$user->notify(new InvoiceNotification($invoice, $user, $payment));
}
/**
* @return JsonResponse|mixed
@ -308,9 +581,13 @@ class PaymentController extends Controller
->editColumn('tax_value', function (Payment $payment) {
return $payment->formatToCurrency($payment->tax_value);
})
->editColumn('tax_percent', function (Payment $payment) {
return $payment->tax_percent . ' %';
})
->editColumn('total_price', function (Payment $payment) {
return $payment->formatToCurrency($payment->total_price);
})
->editColumn('created_at', function (Payment $payment) {
return $payment->created_at ? $payment->created_at->diffForHumans() : '';
})

View file

@ -3,7 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Configuration;
use App\Models\PaypalProduct;
use App\Models\CreditProduct;
use Illuminate\Support\Facades\Auth;
class StoreController extends Controller
@ -11,10 +11,13 @@ class StoreController extends Controller
/** Display a listing of the resource. */
public function index()
{
$isPaypalSetup = false;
if (env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID')) $isPaypalSetup = true;
if (env('APP_ENV', 'local') == 'local') $isPaypalSetup = true;
$isPaymentSetup = false;
if (
env('APP_ENV') == 'local' ||
env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID') ||
env('STRIPE_SECRET') && env('STRIPE_ENDPOINT_SECRET') && env('STRIPE_METHODS')
) $isPaymentSetup = true;
//Required Verification for creating an server
if (Configuration::getValueByKey('FORCE_EMAIL_VERIFICATION', false) === 'true' && !Auth::user()->hasVerifiedEmail()) {
@ -27,8 +30,8 @@ class StoreController extends Controller
}
return view('store.index')->with([
'products' => PaypalProduct::where('disabled', '=', false)->orderBy('price', 'asc')->get(),
'isPaypalSetup' => $isPaypalSetup
'products' => CreditProduct::where('disabled', '=', false)->orderBy('price', 'asc')->get(),
'isPaymentSetup' => $isPaymentSetup,
]);
}
}

View file

@ -12,6 +12,6 @@ class VerifyCsrfToken extends Middleware
* @var array
*/
protected $except = [
//
'payment/StripeWebhooks'
];
}

View file

@ -8,7 +8,7 @@ use NumberFormatter;
use Spatie\Activitylog\Traits\LogsActivity;
use App\Models\Configuration;
class PaypalProduct extends Model
class CreditProduct extends Model
{
use LogsActivity;
/**
@ -33,10 +33,10 @@ class PaypalProduct extends Model
{
parent::boot();
static::creating(function (PaypalProduct $paypalProduct) {
static::creating(function (CreditProduct $creditProduct) {
$client = new Client();
$paypalProduct->{$paypalProduct->getKeyName()} = $client->generateId($size = 21);
$creditProduct->{$creditProduct->getKeyName()} = $client->generateId($size = 21);
});
}

View file

@ -23,8 +23,7 @@ class Payment extends Model
'id',
'user_id',
'payment_id',
'payer_id',
'payer',
'payment_method',
'status',
'type',
'amount',
@ -33,6 +32,7 @@ class Payment extends Model
'total_price',
'tax_percent',
'currency_code',
'credit_product_id',
];
public static function boot()
@ -57,10 +57,10 @@ class Payment extends Model
/**
* @param mixed $value
* @param string $locale
*
*
* @return float
*/
public function formatToCurrency($value,$locale = 'en_US')
public function formatToCurrency($value, $locale = 'en_US')
{
$formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
return $formatter->formatCurrency($value, $this->currency_code);

View file

@ -1,7 +1,7 @@
{
"name": "laravel/laravel",
"name": "cpgg/dashboard",
"type": "project",
"description": "The Laravel Framework.",
"description": "A billing and control panel made for Pterodactyl.",
"keywords": [
"framework",
"laravel"
@ -27,6 +27,7 @@
"spatie/laravel-activitylog": "^3.16",
"spatie/laravel-query-builder": "^3.6",
"spatie/laravel-validation-rules": "^3.0",
"stripe/stripe-php": "^7.107",
"yajra/laravel-datatables-oracle": "~9.0"
},
"require-dev": {

2337
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,72 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Routes group config
|--------------------------------------------------------------------------
|
| The default group settings for the elFinder routes.
|
*/
'route' => [
'prefix' => 'translations',
'middleware' => [
'web',
'auth',
],
],
/**
* Enable deletion of translations
*
* @type boolean
*/
'delete_enabled' => true,
/**
* Exclude specific groups from Laravel Translation Manager.
* This is useful if, for example, you want to avoid editing the official Laravel language files.
*
* @type array
*
* array(
* 'pagination',
* 'reminders',
* 'validation',
* )
*/
'exclude_groups' => [],
/**
* Exclude specific languages from Laravel Translation Manager.
*
* @type array
*
* array(
* 'fr',
* 'de',
* )
*/
'exclude_langs' => [],
/**
* Export translations with keys output alphabetically.
*/
'sort_keys' => false,
'trans_functions' => [
'trans',
'trans_choice',
'Lang::get',
'Lang::choice',
'Lang::trans',
'Lang::transChoice',
'@lang',
'@choice',
'__',
'$trans.get',
],
];

View file

@ -1,38 +0,0 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTranslationsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('ltm_translations', function(Blueprint $table)
{
$table->collation = 'utf8mb4_bin';
$table->bigIncrements('id');
$table->integer('status')->default(0);
$table->string('locale');
$table->string('group');
$table->text('key');
$table->text('value')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('ltm_translations');
}
}

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePaypalProductsTable extends Migration
class CreateCreditProductsTable extends Migration
{
/**
* Run the migrations.
@ -13,7 +13,7 @@ class CreatePaypalProductsTable extends Migration
*/
public function up()
{
Schema::create('paypal_products', function (Blueprint $table) {
Schema::create('credit_products', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('type');
$table->decimal('price')->default(0);
@ -32,6 +32,6 @@ class CreatePaypalProductsTable extends Migration
*/
public function down()
{
Schema::dropIfExists('paypal_products');
Schema::dropIfExists('credit_products');
}
}

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDisplayToPaypalProductsTable extends Migration
class AddDisplayToCreditProductsTable extends Migration
{
/**
* Run the migrations.
@ -13,7 +13,7 @@ class AddDisplayToPaypalProductsTable extends Migration
*/
public function up()
{
Schema::table('paypal_products', function (Blueprint $table) {
Schema::table('credit_products', function (Blueprint $table) {
$table->string('display');
});
}
@ -25,7 +25,7 @@ class AddDisplayToPaypalProductsTable extends Migration
*/
public function down()
{
Schema::table('paypal_products', function (Blueprint $table) {
Schema::table('credit_products', function (Blueprint $table) {
$table->dropColumn('display');
});
}

View file

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
class UpdateToPaymentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('payments', function (Blueprint $table) {
$table->string('payment_method');
$table->dropColumn('payer');
$table->dropColumn('payer_id');
$table->string('credit_product_id');
});
DB::statement('UPDATE payments SET payment_method="paypal"');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('payments', function (Blueprint $table) {
$table->dropColumn('payment_method');
$table->string('payer_id')->nullable();
$table->text('payer')->nullable();
$table->dropColumn('credit_product_id');
});
}
}

View file

@ -3,7 +3,7 @@
namespace Database\Seeders;
use Database\Seeders\Seeds\ProductSeeder;
use Database\Seeders\Seeds\PaypalProductSeeder;
use Database\Seeders\Seeds\CreditProductSeeder;
use Database\Seeders\Seeds\ApplicationApiSeeder;
use Database\Seeders\Seeds\UsefulLinksSeeder;
use Illuminate\Database\Seeder;
@ -19,7 +19,7 @@ class ExampleItemsSeeder extends Seeder
{
$this->call([
ProductSeeder::class,
PaypalProductSeeder::class,
CreditProductSeeder::class,
ApplicationApiSeeder::class,
UsefulLinksSeeder::class
]);

View file

@ -2,10 +2,10 @@
namespace Database\Seeders\Seeds;
use App\Models\PaypalProduct;
use App\Models\CreditProduct;
use Illuminate\Database\Seeder;
class PaypalProductSeeder extends Seeder
class CreditProductSeeder extends Seeder
{
/**
* Run the database seeds.
@ -14,7 +14,7 @@ class PaypalProductSeeder extends Seeder
*/
public function run()
{
PaypalProduct::create([
CreditProduct::create([
'type' => 'Credits',
'display' => '350',
'description' => 'Adds 350 credits to your account',
@ -24,7 +24,7 @@ class PaypalProductSeeder extends Seeder
'disabled' => false,
]);
PaypalProduct::create([
CreditProduct::create([
'type' => 'Credits',
'display' => '875 + 125',
'description' => 'Adds 1000 credits to your account',
@ -34,7 +34,7 @@ class PaypalProductSeeder extends Seeder
'disabled' => false,
]);
PaypalProduct::create([
CreditProduct::create([
'type' => 'Credits',
'display' => '1750 + 250',
'description' => 'Adds 2000 credits to your account',
@ -44,7 +44,7 @@ class PaypalProductSeeder extends Seeder
'disabled' => false,
]);
PaypalProduct::create([
CreditProduct::create([
'type' => 'Credits',
'display' => '3500 + 500',
'description' => 'Adds 4000 credits to your account',

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -95,8 +95,8 @@
"This is what the user sees at checkout": "Dies ist die Beschreibung auf der Rechnung und was der Kunde beim kauf sieht",
"Adds 1000 credits to your account": "Fügt deinem Account 1000 Credits hinzu",
"Active": "Aktiv",
"Paypal is not configured.": "Paypal ist nicht konfiguriert!",
"To configure PayPal, head to the .env and add your PayPals client id and secret.": "Um Paypal zu konfigurieren, füge deine Paypal client ID und Secretkey in deine .env-Datei hinzu",
"No payment method is configured.": "Keine Bezahlmethode konfiguriert!",
"To configure the payment methods, head to the .env and add the required options for your prefered payment method.": "Um die Bezahlmethoden einzustellen, setze die passenden Variablen, für eine oder mehrere Bezahlmethoden, in der .env",
"Useful Links": "Nützliche Links",
"Icon class name": "Icon Klassen-Name",
"You can find available free icons": "Hier gibt es kostenlose Icons",
@ -226,6 +226,7 @@
"Subtotal": "Zwischensumme",
"Submit Payment": "Zahlung bestätigen",
"Payment Methods": "Zahlungsmethoden",
"Payment method": "Zahlungsmethode",
"By purchasing this product you agree and accept our terms of service": "Mit dem kauf akzeptierst du unsere TOS",
"There are no store products!": "Es gibt keine Produkte",
"The store is not correctly configured!": "Der Laden wurde nicht richtig konfiguriert",

View file

@ -5,16 +5,17 @@
"Edit": "Edit",
"Delete": "Delete",
"configuration has been updated!": "configuration has been updated!",
"unknown": "unknown",
"Pterodactyl synced": "Pterodactyl synced",
"Invoice": "Invoice",
"Paid": "Paid",
"Your credit balance has been increased!": "Your credit balance has been increased!",
"Payment was Canceled": "Payment was Canceled",
"Store item has been created!": "Store item has been created!",
"Store item has been updated!": "Store item has been updated!",
"Product has been updated!": "Product has been updated!",
"Store item has been removed!": "Store item has been removed!",
"unknown": "unknown",
"Pterodactyl synced": "Pterodactyl synced",
"Your credit balance has been increased!": "Your credit balance has been increased!",
"Your payment is being processed!": "Your payment is being processed!",
"Your payment has been canceled!": "Your payment has been canceled!",
"Payment method": "Payment method",
"Invoice": "Invoice",
"Product has been created!": "Product has been created!",
"Product has been removed!": "Product has been removed!",
"Show": "Show",
@ -73,6 +74,7 @@
"Regards": "Regards",
"Getting started!": "Getting started!",
"Activity Logs": "Activity Logs",
"Dashboard": "Dashboard",
"No recent activity from cronjobs": "No recent activity from cronjobs",
"Are cronjobs running?": "Are cronjobs running?",
"Check the docs for it here": "Check the docs for it here",
@ -80,7 +82,6 @@
"Description": "Description",
"Created at": "Created at",
"Application API": "Application API",
"Dashboard": "Dashboard",
"Create": "Create",
"Memo": "Memo",
"Submit": "Submit",
@ -95,6 +96,14 @@
"Configurations": "Configurations",
"Key": "Key",
"Value": "Value",
"Nests": "Nests",
"Sync": "Sync",
"Active": "Active",
"ID": "ID",
"eggs": "eggs",
"Name": "Name",
"Nodes": "Nodes",
"Location": "Location",
"Admin Overview": "Admin Overview",
"Support server": "Support server",
"Documentation": "Documentation",
@ -104,26 +113,21 @@
"Total": "Total",
"Payments": "Payments",
"Pterodactyl": "Pterodactyl",
"Sync": "Sync",
"Resources": "Resources",
"Count": "Count",
"Locations": "Locations",
"Nodes": "Nodes",
"Nests": "Nests",
"Eggs": "Eggs",
"Last updated :date": "Last updated :date",
"ID": "ID",
"User": "User",
"Product Price": "Product Price",
"Tax": "Tax",
"Tax Value": "Tax Value",
"Tax Percentage": "Tax Percentage",
"Total Price": "Total Price",
"Payment_ID": "Payment_ID",
"Payer_ID": "Payer_ID",
"Payment ID": "Payment ID",
"Payment Method": "Payment Method",
"Products": "Products",
"Product Details": "Product Details",
"Disabled": "Disabled",
"Will hide this option from being selected": "Will hide this option from being selected",
"Name": "Name",
"Price in": "Price in",
"Memory": "Memory",
"Cpu": "Cpu",
@ -140,10 +144,10 @@
"Link your products to nodes and eggs to create dynamic pricing for each option": "Link your products to nodes and eggs to create dynamic pricing for each option",
"This product will only be available for these nodes": "This product will only be available for these nodes",
"This product will only be available for these eggs": "This product will only be available for these eggs",
"Active": "Active",
"Product": "Product",
"CPU": "CPU",
"Updated at": "Updated at",
"User": "User",
"Config": "Config",
"Suspended at": "Suspended at",
"Settings": "Settings",
@ -170,8 +174,8 @@
"This is what the user sees at store and checkout": "This is what the user sees at store and checkout",
"Adds 1000 credits to your account": "Adds 1000 credits to your account",
"This is what the user sees at checkout": "This is what the user sees at checkout",
"Paypal is not configured.": "Paypal is not configured.",
"To configure PayPal, head to the .env and add your PayPals client id and secret.": "To configure PayPal, head to the .env and add your PayPals client id and secret.",
"No payment method is configured.": "No payment method is configured.",
"To configure the payment methods, head to the .env and add the required options for your prefered payment method.": "To configure the payment methods, head to the .env and add the required options for your prefered payment method.",
"Useful Links": "Useful Links",
"Icon class name": "Icon class name",
"You can find available free icons": "You can find available free icons",
@ -254,7 +258,6 @@
"Please contact support If you didnt receive your verification email.": "Please contact support If you didnt receive your verification email.",
"Thank you for your purchase!": "Thank you for your purchase!",
"Your payment has been confirmed; Your credit balance has been updated.": "Your payment has been confirmed; Your credit balance has been updated.",
"Payment ID": "Payment ID",
"Thanks": "Thanks",
"Redeem voucher code": "Redeem voucher code",
"Close": "Close",
@ -301,7 +304,6 @@
"Please select a configuration ...": "Please select a configuration ...",
"Not enough credits!": "Not enough credits!",
"Create Server": "Create Server",
"Location": "Location",
"Software": "Software",
"Specification": "Specification",
"Resource plan": "Resource plan",
@ -320,8 +322,8 @@
"Pending": "Pending",
"Subtotal": "Subtotal",
"Payment Methods": "Payment Methods",
"By purchasing this product you agree and accept our terms of service": "By purchasing this product you agree and accept our terms of service",
"Amount due": "Amount due",
"Amount Due": "Amount Due",
"Tax": "Tax",
"Submit Payment": "Submit Payment",
"Purchase": "Purchase",
"There are no store products!": "There are no store products!",

View file

@ -10,7 +10,7 @@
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{route('home')}}">{{ __('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.activitylogs.index')}}">{{ __('Activity Logs')}}</a>
</li>
</ol>

View file

@ -11,13 +11,13 @@ THIS FILE IS DEPRECATED
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Nests</h1>
<h1>{{__('Nests')}}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{route('admin.nests.index')}}">Nests</a></li>
href="{{route('admin.nests.index')}}">{{__('Nests')}}</a></li>
</ol>
</div>
</div>
@ -33,9 +33,9 @@ THIS FILE IS DEPRECATED
<div class="card-header">
<div class="d-flex justify-content-between">
<h5 class="card-title"><i class="fas fa-sitemap mr-2"></i>Nests</h5>
<h5 class="card-title"><i class="fas fa-sitemap mr-2"></i>{{__('Nests')}}</h5>
<a href="{{route('admin.nests.sync')}}" class="btn btn-sm btn-info"><i
class="fas fa-sync mr-1"></i>Sync</a>
class="fas fa-sync mr-1"></i>{{__('Sync')}}</a>
</div>
</div>
@ -44,12 +44,12 @@ THIS FILE IS DEPRECATED
<table id="datatable" class="table table-striped">
<thead>
<tr>
<th>Active</th>
<th>ID</th>
<th>eggs</th>
<th>Name</th>
<th>Description</th>
<th>Created at</th>
<th>{{__('Active')}}</th>
<th>{{__('ID')}}</th>
<th>{{__('eggs')}}</th>
<th>{{__('Name')}}</th>
<th>{{__('Description')}}</th>
<th>{{__('Created at')}}</th>
</tr>
</thead>
@ -69,7 +69,7 @@ THIS FILE IS DEPRECATED
<script>
function submitResult() {
return confirm("Are you sure you wish to delete?") !== false;
return confirm({{__("Are you sure you wish to delete?")}}) !== false;
}
document.addEventListener("DOMContentLoaded", function () {

View file

@ -11,13 +11,13 @@ THIS FILE IS DEPRECATED
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Nodes</h1>
<h1>{{__('Nodes')}}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{route('admin.nodes.index')}}">Nodes</a></li>
href="{{route('admin.nodes.index')}}">{{__('Nodes')}}</a></li>
</ol>
</div>
</div>
@ -33,9 +33,9 @@ THIS FILE IS DEPRECATED
<div class="card-header">
<div class="d-flex justify-content-between">
<h5 class="card-title"><i class="fas fa-sitemap mr-2"></i>Nodes</h5>
<h5 class="card-title"><i class="fas fa-sitemap mr-2"></i>{{__('Nodes')}}</h5>
<a href="{{route('admin.nodes.sync')}}" class="btn btn-sm btn-info"><i
class="fas fa-sync mr-1"></i>Sync</a>
class="fas fa-sync mr-1"></i>{{__('Sync')}}</a>
</div>
</div>
@ -44,12 +44,12 @@ THIS FILE IS DEPRECATED
<table id="datatable" class="table table-striped">
<thead>
<tr>
<th>Active</th>
<th>ID</th>
<th>Location</th>
<th>Name</th>
<th>Description</th>
<th>Created at</th>
<th>{{__('Active')}}</th>
<th>{{__('ID')}}</th>
<th>{{__('Location')}}</th>
<th>{{__('Name')}}</th>
<th>{{__('Description')}}</th>
<th>{{__('Created at')}}</th>
</tr>
</thead>
@ -69,7 +69,7 @@ THIS FILE IS DEPRECATED
<script>
function submitResult() {
return confirm("Are you sure you wish to delete?") !== false;
return confirm({{__("Are you sure you wish to delete?")}}) !== false;
}
document.addEventListener("DOMContentLoaded", function () {

View file

@ -26,25 +26,24 @@
<div class="card">
<div class="card-header">
<h5 class="card-title"><i class="fas fa-money-bill-wave mr-2"></i>{{__('Payments')}}</h5>
<h5 class="card-title"><i class="fas fa-money-bill-wave mr-2"></i>{{ __('Payments') }}</h5>
</div>
<div class="card-body table-responsive">
<table id="datatable" class="table table-striped">
<thead>
<tr>
<th>{{__('ID')}}</th>
<th>{{__('User')}}</th>
<th>{{__('Type')}}</th>
<th>{{__('Amount')}}</th>
<th>{{__('Product Price')}}</th>
<th>{{__('Tax')}}</th>
<th>{{__('Tax')}}(%)</th>
<th>{{__('Total Price')}}</th>
<th>{{__('Payment_ID')}}</th>
<th>{{__('Payer_ID')}}</th>
<th>{{__('Created at')}}</th>
</tr>
<tr>
<th>{{ __('ID') }}</th>
<th>{{ __('Type') }}</th>
<th>{{ __('Amount') }}</th>
<th>{{ __('Product Price') }}</th>
<th>{{ __('Tax Value') }}</th>
<th>{{ __('Tax Percentage') }}</th>
<th>{{ __('Total Price') }}</th>
<th>{{ __('Payment ID') }}</th>
<th>{{ __('Payment Method') }}</th>
<th>{{ __('Created at') }}</th>
</tr>
</thead>
<tbody>
</tbody>
@ -59,7 +58,7 @@
<!-- END CONTENT -->
<script>
document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("DOMContentLoaded", function() {
$('#datatable').DataTable({
language: {
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("app.datatable_locale")}}.json'
@ -67,10 +66,9 @@
processing: true,
serverSide: true,
stateSave: true,
ajax: "{{route('admin.payments.datatable')}}",
ajax: "{{ route('admin.payments.datatable') }}",
columns: [
{data: 'id' , name : 'payments.id'},
{data: 'user', sortable: false},
{data: 'id',name: 'payments.id'},
{data: 'type'},
{data: 'amount'},
{data: 'price'},
@ -78,12 +76,12 @@
{data: 'tax_percent'},
{data: 'total_price'},
{data: 'payment_id'},
{data: 'payer_id'},
{data: 'payment_method'},
{data: 'created_at'},
],
fnDrawCallback: function( oSettings ) {
fnDrawCallback: function(oSettings) {
$('[data-toggle="popover"]').popover();
}
},
});
});
</script>

View file

@ -6,14 +6,14 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Store')}}</h1>
<h1>{{ __('Store') }}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a href="{{route('admin.store.index')}}">{{__('Store')}}</a></li>
<li class="breadcrumb-item"><a href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.store.index') }}">{{ __('Store') }}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{route('admin.store.edit' , $paypalProduct->id)}}">{{__('Edit')}}</a>
href="{{ route('admin.store.edit', $creditProduct->id) }}">{{ __('Edit') }}</a>
</li>
</ol>
</div>
@ -30,127 +30,115 @@
<div class="col-lg-6">
<div class="card">
<div class="card-body">
<form action="{{route('admin.store.update' , $paypalProduct->id)}}" method="POST">
<form action="{{ route('admin.store.update', $creditProduct->id) }}" method="POST">
@csrf
@method('PATCH')
<div class="d-flex flex-row-reverse">
<div class="custom-control custom-switch">
<input type="checkbox" @if($paypalProduct->disabled) checked
@endif name="disabled"
class="custom-control-input custom-control-input-danger"
id="switch1">
<label class="custom-control-label" for="switch1">{{__('Disabled')}} <i
data-toggle="popover"
data-trigger="hover"
data-content="{{__('Will hide this option from being selected')}}"
<input type="checkbox" @if ($creditProduct->disabled) checked @endif name="disabled"
class="custom-control-input custom-control-input-danger" id="switch1">
<label class="custom-control-label" for="switch1">{{ __('Disabled') }} <i
data-toggle="popover" data-trigger="hover"
data-content="{{ __('Will hide this option from being selected') }}"
class="fas fa-info-circle"></i></label>
</div>
</div>
<div class="form-group">
<label for="type">{{__('Type')}}</label>
<label for="type">{{ __('Type') }}</label>
<select required name="type" id="type"
class="custom-select @error('name') is-invalid @enderror">
<option selected value="Credits">{{CREDITS_DISPLAY_NAME}}</option>
class="custom-select @error('name') is-invalid @enderror">
<option selected value="Credits">{{ CREDITS_DISPLAY_NAME }}</option>
</select>
@error('name')
<div class="text-danger">
{{$message}}
</div>
<div class="text-danger">
{{ $message }}
</div>
@enderror
</div>
<div class="form-group">
<label for="currency_code">{{__('Currency code')}}</label>
<label for="currency_code">{{ __('Currency code') }}</label>
<select required name="currency_code" id="currency_code"
class="custom-select @error('name') is-invalid @enderror">
@foreach($currencyCodes as $code)
<option @if($paypalProduct->currency_code == $code) selected
@endif value="{{$code}}">{{$code}}</option>
class="custom-select @error('name') is-invalid @enderror">
@foreach ($currencyCodes as $code)
<option @if ($creditProduct->currency_code == $code) selected @endif value="{{ $code }}">
{{ $code }}</option>
@endforeach
</select>
@error('currency_code')
<div class="text-danger">
{{$message}}
</div>
<div class="text-danger">
{{ $message }}
</div>
@enderror
<div class="text-muted">
{{__('Checkout the paypal docs to select the appropriate code')}} <a
{{ __('Checkout the paypal docs to select the appropriate code') }} <a
target="_blank"
href="https://developer.paypal.com/docs/api/reference/currency-codes/">link</a>
</div>
</div>
<div class="form-group">
<label for="price">{{__('Price')}}</label>
<input value="{{$paypalProduct->price}}" id="price" name="price"
type="number"
placeholder="10.00"
step="any"
class="form-control @error('price') is-invalid @enderror"
required="required">
<label for="price">Price</label>
<input value="{{ $creditProduct->price }}" id="price" name="price" type="number"
placeholder="10.00" step="any"
class="form-control @error('price') is-invalid @enderror" required="required">
@error('price')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="form-group">
<label for="quantity">{{__('Quantity')}}</label>
<input value="{{$paypalProduct->quantity}}" id="quantity" name="quantity"
type="number"
placeholder="1000"
class="form-control @error('quantity') is-invalid @enderror"
required="required">
<label for="quantity">Quantity</label>
<input value="{{ $creditProduct->quantity }}" id="quantity" name="quantity"
type="number" placeholder="1000"
class="form-control @error('quantity') is-invalid @enderror" required="required">
@error('quantity')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
<div class="text-muted">
{{__('Amount given to the user after purchasing')}}
{{ __('Amount given to the user after purchasing') }}
</div>
</div>
<div class="form-group">
<label for="display">{{__('Display')}}</label>
<input value="{{$paypalProduct->display}}" id="display" name="display"
type="text"
placeholder="750 + 250"
class="form-control @error('display') is-invalid @enderror"
required="required">
<label for="display">Display</label>
<input value="{{ $creditProduct->display }}" id="display" name="display" type="text"
placeholder="750 + 250" class="form-control @error('display') is-invalid @enderror"
required="required">
@error('display')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
<div class="text-muted">
{{__('This is what the user sees at store and checkout')}}
{{ __('This is what the user sees at store and checkout') }}
</div>
</div>
<div class="form-group">
<label for="description">{{__('Description')}}</label>
<input value="{{$paypalProduct->description}}" id="description" name="description"
type="text"
placeholder="{{__('Adds 1000 credits to your account')}}"
class="form-control @error('description') is-invalid @enderror"
required="required">
<label for="description">Description</label>
<input value="{{ $creditProduct->description }}" id="description" name="description"
type="text" placeholder="{{ __('Adds 1000 credits to your account') }}"
class="form-control @error('description') is-invalid @enderror" required="required">
@error('description')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
<div class="text-muted">
{{__('This is what the user sees at checkout')}}
{{ __('This is what the user sees at checkout') }}
</div>
</div>
<div class="form-group text-right">
<button type="submit" class="btn btn-primary">
{{__('Submit')}}
{{ __('Submit') }}
</button>
</div>
</form>

View file

@ -6,13 +6,13 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Store')}}</h1>
<h1>{{ __('Store') }}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{route('admin.store.index')}}">{{__('Store')}}</a></li>
href="{{ route('admin.store.index') }}">{{ __('Store') }}</a></li>
</ol>
</div>
</div>
@ -26,12 +26,14 @@
<div class="row">
<div class="col-lg-4">
@if($isPaypalSetup == false)
@if ($isPaymentSetup == false)
<div class="callout callout-danger">
<h4>{{__('Paypal is not configured.')}}</h4>
<p>{{__('To configure PayPal, head to the .env and add your PayPals client id and secret.')}}</p>
<h4>{{ __('No payment method is configured.') }}</h4>
<p>{{ __('To configure the payment methods, head to the .env and add the required options for your prefered payment method.') }}
</p>
</div>
@endif
</div>
</div>
@ -39,9 +41,9 @@
<div class="card-header">
<div class="d-flex justify-content-between">
<h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>{{__('Store')}}</h5>
<a href="{{route('admin.store.create')}}" class="btn btn-sm btn-primary"><i
class="fas fa-plus mr-1"></i>{{__('Create new')}}</a>
<h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>{{ __('Store') }}</h5>
<a href="{{ route('admin.store.create') }}" class="btn btn-sm btn-primary"><i
class="fas fa-plus mr-1"></i>{{ __('Create new') }}</a>
</div>
</div>
@ -49,15 +51,15 @@
<table id="datatable" class="table table-striped">
<thead>
<tr>
<th>{{__('Active')}}</th>
<th>{{__('Type')}}</th>
<th>{{__('Price')}}</th>
<th>{{__('Display')}}</th>
<th>{{__('Description')}}</th>
<th>{{__('Created at')}}</th>
<th></th>
</tr>
<tr>
<th>{{ __('Active') }}</th>
<th>{{ __('Type') }}</th>
<th>{{ __('Price') }}</th>
<th>{{ __('Display') }}</th>
<th>{{ __('Description') }}</th>
<th>{{ __('Created at') }}</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
@ -78,26 +80,42 @@
return confirm("Are you sure you wish to delete?") !== false;
}
document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("DOMContentLoaded", function() {
$('#datatable').DataTable({
language: {
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("app.datatable_locale")}}.json'
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{ config('app.datatable_locale') }}.json'
},
processing: true,
serverSide: true,
stateSave: true,
ajax: "{{route('admin.store.datatable')}}",
order: [[ 2, "desc" ]],
columns: [
{data: 'disabled'},
{data: 'type'},
{data: 'price'},
{data: 'display'},
{data: 'description'},
{data: 'created_at'},
{data: 'actions', sortable: false},
ajax: "{{ route('admin.store.datatable') }}",
order: [
[2, "desc"]
],
fnDrawCallback: function( oSettings ) {
columns: [{
data: 'disabled'
},
{
data: 'type'
},
{
data: 'price'
},
{
data: 'display'
},
{
data: 'description'
},
{
data: 'created_at'
},
{
data: 'actions',
sortable: false
},
],
fnDrawCallback: function(oSettings) {
$('[data-toggle="popover"]').popover();
}
});

View file

@ -6,12 +6,15 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Store')}}</h1>
<h1>{{ __('Store') }}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a class="" href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a class="text-muted" href="{{route('store.index')}}">{{__('Store')}}</a></li>
<li class="breadcrumb-item"><a class=""
href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{ route('store.index') }}">{{ __('Store') }}</a>
</li>
</ol>
</div>
</div>
@ -20,7 +23,7 @@
<!-- END CONTENT HEADER -->
<!-- MAIN CONTENT -->
<section class="content">
<section x-data="serverApp()" x-init="$watch('paymentMethod', value => setPaymentRoute(value))" class="content">
<div class="container-fluid">
<div class="row">
@ -34,7 +37,8 @@
<div class="col-12">
<h4>
<i class="fas fa-globe"></i> {{ config('app.name', 'Laravel') }}
<small class="float-right">{{__('Date')}}: {{Carbon\Carbon::now()->isoFormat('LL')}}</small>
<small class="float-right">{{ __('Date') }}:
{{ Carbon\Carbon::now()->isoFormat('LL') }}</small>
</h4>
</div>
<!-- /.col -->
@ -42,25 +46,25 @@
<!-- info row -->
<div class="row invoice-info">
<div class="col-sm-4 invoice-col">
{{__('To')}}
{{ __('To') }}
<address>
<strong>{{config('app.name' , 'Laravel')}}</strong><br>
{{__('Email')}}: {{env('PAYPAL_EMAIL' , env('MAIL_FROM_NAME'))}}
<strong>{{ config('app.name', 'Controlpanel.GG') }}</strong><br>
{{ __('Email') }}: {{ env('PAYPAL_EMAIL', env('MAIL_FROM_NAME')) }}
</address>
</div>
<!-- /.col -->
<div class="col-sm-4 invoice-col">
{{__('From')}}
{{ __('From') }}
<address>
<strong>{{Auth::user()->name}}</strong><br>
{{__('Email')}}: {{Auth::user()->email}}
<strong>{{ Auth::user()->name }}</strong><br>
{{ __('Email') }}: {{ Auth::user()->email }}
</address>
</div>
<!-- /.col -->
<div class="col-sm-4 invoice-col">
<b>{{__('Status')}}</b><br>
<span class="badge badge-warning">{{__('Pending')}}</span><br>
{{-- <b>Order ID:</b> 4F3S8J<br>--}}
<b>{{ __('Status') }}</b><br>
<span class="badge badge-warning">{{ __('Pending') }}</span><br>
{{-- <b>Order ID:</b> 4F3S8J<br> --}}
</div>
<!-- /.col -->
</div>
@ -71,20 +75,22 @@
<div class="col-12 table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>{{__('Quantity')}}</th>
<th>{{__('Product')}}</th>
<th>{{__('Description')}}</th>
<th>{{__('Subtotal')}}</th>
</tr>
<tr>
<th>{{ __('Quantity') }}</th>
<th>{{ __('Product') }}</th>
<th>{{ __('Description') }}</th>
<th>{{ __('Subtotal') }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><i class="fa fa-coins mr-2"></i>{{$product->quantity}} {{strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type}}</td>
<td>{{$product->description}}</td>
<td>{{$product->formatToCurrency($product->price)}}</td>
</tr>
<tr>
<td>1</td>
<td><i class="fa fa-coins mr-2"></i>{{ $product->quantity }}
{{ strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type }}
</td>
<td>{{ $product->description }}</td>
<td>{{ $product->formatToCurrency($product->price) }}</td>
</tr>
</tbody>
</table>
</div>
@ -95,35 +101,53 @@
<div class="row">
<!-- accepted payments column -->
<div class="col-6">
<p class="lead">{{__('Payment Methods')}}:</p>
<p class="lead">{{ __('Payment Methods') }}:</p>
<img src="https://www.paypalobjects.com/digitalassets/c/website/logo/full-text/pp_fc_hl.svg" alt="Paypal">
<div>
@if (env('PAYPAL_SANDBOX_SECRET') || env('PAYPAL_SECRET'))
<label class="text-center " for="paypal">
<img class="mb-3" height="50"
src="{{ url('/images/paypal_logo.png') }}"></br>
<input x-model="paymentMethod" type="radio" id="paypal" value="paypal"
name="payment_method">
</input>
</label>
@endif
@if (env('STRIPE_TEST_SECRET') || env('STRIPE_SECRET'))
<label class="ml-5 text-center " for="stripe">
<img class="mb-3" height="50"
src="{{ url('/images/stripe_logo.png') }}" /></br>
<input x-model="paymentMethod" type="radio" id="stripe" value="stripe"
name="payment_method">
</input>
</label>
@endif
</div>
<p class="text-muted well well-sm shadow-none" style="margin-top: 10px;">
{{__('By purchasing this product you agree and accept our terms of service')}}</a>
</p>
</div>
<!-- /.col -->
<div class="col-6">
<p class="lead">{{__('Amount due')}} {{Carbon\Carbon::now()->isoFormat('LL')}}</p>
<p class="lead">{{ __('Amount Due') }}
{{ Carbon\Carbon::now()->isoFormat('LL') }}</p>
<div class="table-responsive">
<table class="table">
<tr>
<th style="width:50%">{{__('Subtotal')}}:</th>
<td>{{$product->formatToCurrency($product->price)}}</td>
<th style="width:50%">{{ __('Subtotal') }}:</th>
<td>{{ $product->formatToCurrency($product->price) }}</td>
</tr>
<tr>
<th>{{__('Tax')}} ({{$taxpercent}}%)</th>
<td>{{$product->formatToCurrency($taxvalue)}}</td>
<th>{{ __('Tax') }} ({{ $taxpercent }}%)</th>
<td>{{ $product->formatToCurrency($taxvalue) }}</td>
</tr>
<tr>
<th>{{__('Quantity')}}:</th>
<th>{{ __('Quantity') }}:</th>
<td>1</td>
</tr>
<tr>
<th>{{__('Total')}}:</th>
<td>{{$product->formatToCurrency($total)}}</td>
<th>{{ __('Total') }}:</th>
<td>{{ $product->formatToCurrency($total) }}</td>
</tr>
</table>
</div>
@ -135,7 +159,10 @@
<!-- this row will not appear when printing -->
<div class="row no-print">
<div class="col-12">
<a href="{{route('payment.pay' , $product->id)}}" type="button" class="btn btn-success float-right"><i class="far fa-credit-card mr-2"></i> {{__('Submit Payment')}}
<a type="button" :href="paymentRoute" :disabled="!paymentRoute"
:class="!paymentRoute ? 'disabled' : ''" class="btn btn-success float-right"><i
class="far fa-credit-card mr-2"></i>
{{ __('Submit Payment') }}
</a>
</div>
</div>
@ -143,10 +170,35 @@
<!-- /.invoice -->
</div><!-- /.col -->
</div><!-- /.row -->
</div>
</section>
<!-- END CONTENT -->
<script>
function serverApp() {
return {
//loading
paymentMethod: '',
paymentRoute: '',
setPaymentRoute(provider) {
switch (provider) {
case 'paypal':
this.paymentRoute = '{{ route('payment.PaypalPay', $product->id) }}';
break;
case 'stripe':
this.paymentRoute = '{{ route('payment.StripePay', $product->id) }}';
break;
default:
this.paymentRoute = '{{ route('payment.PaypalPay', $product->id) }}';
}
},
}
}
</script>
@endsection

View file

@ -1,5 +1,5 @@
@extends('layouts.main')
<?php use App\Models\PaypalProduct; ?>
<?php use App\Models\CreditProduct; ?>
@section('content')
<!-- CONTENT HEADER -->
@ -7,12 +7,14 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Store')}}</h1>
<h1>{{ __('Store') }}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a class="" href="{{route('home')}}">{{__('Dashboard')}}</a></li>
<li class="breadcrumb-item"><a class="text-muted" href="{{route('store.index')}}">{{__('Store')}}</a></li>
<li class="breadcrumb-item"><a class=""
href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{ route('store.index') }}">{{ __('Store') }}</a></li>
</ol>
</div>
</div>
@ -26,37 +28,40 @@
<div class="text-right mb-3">
<button type="button" data-toggle="modal" data-target="#redeemVoucherModal" class="btn btn-primary">
<i class="fas fa-money-check-alt mr-2"></i>{{__('Redeem code')}}
<i class="fas fa-money-check-alt mr-2"></i>{{ __('Redeem code') }}
</button>
</div>
@if($isPaypalSetup && $products->count() > 0)
@if ($isPaymentSetup && $products->count() > 0)
<div class="card">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-coins mr-2"></i>{{CREDITS_DISPLAY_NAME}}</h5>
<h5 class="card-title"><i class="fa fa-coins mr-2"></i>{{ CREDITS_DISPLAY_NAME }}</h5>
</div>
<div class="card-body">
<table class="table table-striped table-responsive-sm">
<thead>
<tr>
<th>{{__('Price')}}</th>
<th>{{__('Type')}}</th>
<th>{{__('Description')}}</th>
<th></th>
</tr>
<tr>
<th>{{ __('Price') }}</th>
<th>{{ __('Type') }}</th>
<th>{{ __('Description') }}</th>
<th></th>
</tr>
</thead>
<tbody>
<?php /** @var $product PaypalProduct */?>
@foreach($products as $product)
<tr>
<td>{{$product->formatToCurrency($product->price)}}</td>
<td>{{strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type}}</td>
<td><i class="fa fa-coins mr-2"></i>{{$product->display}}</td>
<td><a href="{{route('checkout' , $product->id)}}" class="btn btn-info">{{__('Purchase')}}</a>
</td>
</tr>
@endforeach
<?php /** @var $product CreditProduct */
?>
@foreach ($products as $product)
<tr>
<td>{{ $product->formatToCurrency($product->price) }}</td>
<td>{{ strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type }}
</td>
<td><i class="fa fa-coins mr-2"></i>{{ $product->display }}</td>
<td><a href="{{ route('checkout', $product->id) }}"
class="btn btn-info">{{ __('Purchase') }}</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@ -65,7 +70,7 @@
@else
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> @if($products->count() == 0) {{__('There are no store products!')}} @else {{__('The store is not correctly configured!')}} @endif
<h4><i class="icon fa fa-ban"></i> @if ($products->count() == 0) {{ __('There are no store products!') }} @else {{ __('The store is not correctly configured!') }} @endif
</h4>
</div>

View file

@ -5,7 +5,7 @@ use App\Http\Controllers\Admin\ApplicationApiController;
use App\Http\Controllers\Admin\ConfigurationController;
use App\Http\Controllers\Admin\OverViewController;
use App\Http\Controllers\Admin\PaymentController;
use App\Http\Controllers\Admin\PaypalProductController;
use App\Http\Controllers\Admin\CreditProductController;
use App\Http\Controllers\Admin\ProductController;
use App\Http\Controllers\Admin\ServerController as AdminServerController;
use App\Http\Controllers\Admin\SettingsController;
@ -40,6 +40,9 @@ Route::middleware('guest')->get('/', function () {
Auth::routes(['verify' => true]);
# Stripe WebhookRoute -> validation in Route Handler
Route::post('payment/StripeWebhooks', [PaymentController::class, 'StripeWebhooks'])->name('payment.StripeWebhooks');
Route::middleware(['auth', 'checkSuspended'])->group(function () {
#resend verification email
Route::get('/email/verification-notification', function (Request $request) {
@ -61,10 +64,14 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
Route::get('/products/products/{egg?}/{node?}', [FrontProductController::class, 'getProductsBasedOnNode'])->name('products.products.node');
#payments
Route::get('checkout/{paypalProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
Route::get('payment/success', [PaymentController::class, 'success'])->name('payment.success');
Route::get('payment/cancel', [PaymentController::class, 'cancel'])->name('payment.cancel');
Route::get('payment/pay/{paypalProduct}', [PaymentController::class, 'pay'])->name('payment.pay');
Route::get('checkout/{creditProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
Route::get('payment/PaypalPay/{creditProduct}', [PaymentController::class, 'PaypalPay'])->name('payment.PaypalPay');
Route::get('payment/PaypalSuccess', [PaymentController::class, 'PaypalSuccess'])->name('payment.PaypalSuccess');
Route::get('payment/StripePay/{creditProduct}', [PaymentController::class, 'StripePay'])->name('payment.StripePay');
Route::get('payment/StripeSuccess', [PaymentController::class, 'StripeSuccess'])->name('payment.StripeSuccess');
Route::get('payment/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
Route::get('users/logbackin', [UserController::class, 'logBackIn'])->name('users.logbackin');
@ -100,10 +107,10 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
Route::patch('products/disable/{product}', [ProductController::class, 'disable'])->name('products.disable');
Route::resource('products', ProductController::class);
Route::get('store/datatable', [PaypalProductController::class, 'datatable'])->name('store.datatable');
Route::patch('store/disable/{paypalProduct}', [PaypalProductController::class, 'disable'])->name('store.disable');
Route::resource('store', PaypalProductController::class)->parameters([
'store' => 'paypalProduct',
Route::get('store/datatable', [CreditProductController::class, 'datatable'])->name('store.datatable');
Route::patch('store/disable/{creditProduct}', [CreditProductController::class, 'disable'])->name('store.disable');
Route::resource('store', CreditProductController::class)->parameters([
'store' => 'creditProduct',
]);
Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');