diff --git a/app/Events/PaymentEvent.php b/app/Events/PaymentEvent.php
new file mode 100644
index 00000000..11711200
--- /dev/null
+++ b/app/Events/PaymentEvent.php
@@ -0,0 +1,31 @@
+user = $user;
+ $this->payment = $payment;
+ $this->shopProduct = $shopProduct;
+ }
+}
diff --git a/app/Extensions/PaymentGateways/PayPal/index.php b/app/Extensions/PaymentGateways/PayPal/index.php
new file mode 100644
index 00000000..aeb2310b
--- /dev/null
+++ b/app/Extensions/PaymentGateways/PayPal/index.php
@@ -0,0 +1,216 @@
+shopProduct);
+
+ // create a new payment
+ $payment = Payment::create([
+ 'user_id' => $user->id,
+ 'payment_id' => null,
+ 'payment_method' => 'paypal',
+ 'type' => $shopProduct->type,
+ 'status' => 'open',
+ 'amount' => $shopProduct->quantity,
+ 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
+ 'tax_value' => $shopProduct->getTaxValue(),
+ 'tax_percent' => $shopProduct->getTaxPercent(),
+ 'total_price' => $shopProduct->getTotalPrice(),
+ 'currency_code' => $shopProduct->currency_code,
+ 'shop_item_product_id' => $shopProduct->id,
+ ]);
+
+ $request = new OrdersCreateRequest();
+ $request->prefer('return=representation');
+ $request->body = [
+ "intent" => "CAPTURE",
+ "purchase_units" => [
+ [
+ "reference_id" => uniqid(),
+ "description" => $shopProduct->display . (PartnerDiscount::getDiscount() ? (" (" . __('Discount') . " " . PartnerDiscount::getDiscount() . '%)') : ""),
+ "amount" => [
+ "value" => $shopProduct->getTotalPrice(),
+ 'currency_code' => strtoupper($shopProduct->currency_code),
+ 'breakdown' => [
+ 'item_total' =>
+ [
+ 'currency_code' => strtoupper($shopProduct->currency_code),
+ 'value' => $shopProduct->getPriceAfterDiscount(),
+ ],
+ 'tax_total' =>
+ [
+ 'currency_code' => strtoupper($shopProduct->currency_code),
+ 'value' => $shopProduct->getTaxValue(),
+ ]
+ ]
+ ]
+ ]
+ ],
+ "application_context" => [
+ "cancel_url" => route('payment.Cancel'),
+ "return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]),
+ 'brand_name' => config('app.name', 'Laravel'),
+ 'shipping_preference' => 'NO_SHIPPING'
+ ]
+
+
+ ];
+
+ try {
+ // Call API with your client and get a response for your call
+ $response = getPayPalClient()->execute($request);
+
+ Redirect::away($response->result->links[1]->href)->send();
+ return;
+ } catch (HttpException $ex) {
+ error_log($ex->statusCode);
+ error_log($ex->getMessage());
+
+ $payment->delete();
+ Redirect::route('payment.Cancel');
+ return;
+ }
+}
+/**
+ * @param Request $laravelRequest
+ */
+function PaypalSuccess(Request $laravelRequest)
+{
+ $user = Auth::user();
+ $user = User::findOrFail($user->id);
+
+ $payment = Payment::findOrFail($laravelRequest->payment);
+ $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
+
+ $request = new OrdersCaptureRequest($laravelRequest->input('token'));
+ $request->prefer('return=representation');
+
+ try {
+ // Call API with your client and get a response for your call
+ $response = getPayPalClient()->execute($request);
+ if ($response->statusCode == 201 || $response->statusCode == 200) {
+ //update payment
+ $payment->update([
+ 'status' => 'paid',
+ 'payment_id' => $response->result->id,
+ ]);
+
+ event(new UserUpdateCreditsEvent($user));
+ event(new PaymentEvent($user, $payment, $shopProduct));
+
+ // redirect to the payment success page with success message
+ Redirect::route('home')->with('success', 'Payment successful')->send();
+ } elseif (env('APP_ENV') == 'local') {
+ // If call returns body in response, you can get the deserialized version from the result attribute of the response
+ $payment->delete();
+ dd($response);
+ } else {
+ $payment->update([
+ 'status' => 'cancelled',
+ 'payment_id' => $response->result->id,
+ ]);
+ abort(500);
+ }
+ } catch (HttpException $ex) {
+ if (env('APP_ENV') == 'local') {
+ echo $ex->statusCode;
+ $payment->delete();
+ dd($ex->getMessage());
+ } else {
+ $payment->update([
+ 'status' => 'cancelled',
+ 'payment_id' => $response->result->id,
+ ]);
+ abort(422);
+ }
+ }
+}
+/**
+ * @return PayPalHttpClient
+ */
+function getPayPalClient()
+{
+ $environment = env('APP_ENV') == 'local'
+ ? new SandboxEnvironment(getPaypalClientId(), getPaypalClientSecret())
+ : new ProductionEnvironment(getPaypalClientId(), getPaypalClientSecret());
+ return new PayPalHttpClient($environment);
+}
+/**
+ * @return string
+ */
+function getPaypalClientId()
+{
+ return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
+}
+/**
+ * @return string
+ */
+function getPaypalClientSecret()
+{
+ return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : config("SETTINGS::PAYMENTS:PAYPAL:SECRET");
+}
+function getPayPalConfig()
+{
+ return [
+ "name" => "PayPal",
+ "description" => "PayPal payment gateway",
+ "settings" => [
+ "mode" => [
+ "type" => "select",
+ "label" => "Mode",
+ "value" => config("APP_ENV") == 'local' ? "sandbox" : "live",
+ "options" => [
+ "sandbox" => "Sandbox",
+ "live" => "Live",
+ ],
+ ],
+ "CLIENT_ID" => [
+ "type" => "text",
+ "label" => "PayPal Client ID",
+ "value" => config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID"),
+ ],
+ "SECRET" => [
+ "type" => "text",
+ "label" => "PayPal Secret",
+ "value" => config("SETTINGS::PAYMENTS:PAYPAL:SECRET"),
+ ],
+ "SANDBOX_CLIENT_ID" => [
+ "type" => "text",
+ "label" => "PayPal Sandbox Client ID",
+ "value" => config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID"),
+ ],
+ "SANDBOX_SECRET" => [
+ "type" => "text",
+ "label" => "PayPal Sandbox Secret",
+ "value" => config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET"),
+ ],
+ ],
+ ];
+}
diff --git a/app/Extensions/PaymentGateways/PayPal/web_routes.php b/app/Extensions/PaymentGateways/PayPal/web_routes.php
new file mode 100644
index 00000000..56497768
--- /dev/null
+++ b/app/Extensions/PaymentGateways/PayPal/web_routes.php
@@ -0,0 +1,18 @@
+group(function () {
+ Route::get('payment/PayPalPay/{shopProduct}', function () {
+ PaypalPay(request());
+ })->name('payment.PayPalPay');
+
+ Route::get(
+ 'payment/PayPalSuccess',
+ function () {
+ PaypalSuccess(request());
+ }
+ )->name('payment.PayPalSuccess');
+});
diff --git a/app/Extensions/PaymentGateways/Stripe/index.php b/app/Extensions/PaymentGateways/Stripe/index.php
new file mode 100644
index 00000000..ea0369e8
--- /dev/null
+++ b/app/Extensions/PaymentGateways/Stripe/index.php
@@ -0,0 +1,402 @@
+shopProduct);
+
+ // check if the price is valid for stripe
+ if (!checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
+ Redirect::route('home')->with('error', __('The product you chose can\'t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'))->send();
+ return;
+ }
+
+
+ // create payment
+ $payment = Payment::create([
+ 'user_id' => $user->id,
+ 'payment_id' => null,
+ 'payment_method' => 'stripe',
+ 'type' => $shopProduct->type,
+ 'status' => 'open',
+ 'amount' => $shopProduct->quantity,
+ 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
+ 'tax_value' => $shopProduct->getTaxValue(),
+ 'total_price' => $shopProduct->getTotalPrice(),
+ 'tax_percent' => $shopProduct->getTaxPercent(),
+ 'currency_code' => $shopProduct->currency_code,
+ 'shop_item_product_id' => $shopProduct->id,
+ ]);
+
+ $stripeClient = getStripeClient();
+ $request = $stripeClient->checkout->sessions->create([
+ 'line_items' => [
+ [
+ 'price_data' => [
+ 'currency' => $shopProduct->currency_code,
+ 'product_data' => [
+ 'name' => $shopProduct->display . (PartnerDiscount::getDiscount() ? (' (' . __('Discount') . ' ' . PartnerDiscount::getDiscount() . '%)') : ''),
+ 'description' => $shopProduct->description,
+ ],
+ 'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
+ ],
+ 'quantity' => 1,
+ ],
+ [
+ 'price_data' => [
+ 'currency' => $shopProduct->currency_code,
+ 'product_data' => [
+ 'name' => __('Tax'),
+ 'description' => $shopProduct->getTaxPercent() . '%',
+ ],
+ 'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
+ ],
+ 'quantity' => 1,
+ ],
+ ],
+
+ 'mode' => 'payment',
+ 'payment_method_types' => str_getcsv(config('SETTINGS::PAYMENTS:STRIPE:METHODS')),
+ 'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
+ 'cancel_url' => route('payment.Cancel'),
+ ]);
+
+ Redirect::to($request->url)->send();
+}
+
+/**
+ * @param Request $request
+ */
+function StripeSuccess(Request $request)
+{
+ $user = Auth::user();
+ $user = User::findOrFail($user->id);
+ $payment = Payment::findOrFail($request->input('payment'));
+ $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
+
+
+ $stripeClient = 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 payment
+ $payment->update([
+ 'payment_id' => $paymentSession->payment_intent,
+ 'status' => 'paid',
+ ]);
+
+ //payment notification
+ $user->notify(new ConfirmPaymentNotification($payment));
+
+ event(new UserUpdateCreditsEvent($user));
+ event(new PaymentEvent($user, $payment, $shopProduct));
+
+ //redirect back to home
+ Redirect::route('home')->with('success', 'Payment successful')->send();
+ } else {
+ if ($paymentIntent->status == 'processing') {
+
+ //update payment
+ $payment->update([
+ 'payment_id' => $paymentSession->payment_intent,
+ 'status' => 'processing',
+ ]);
+
+ event(new PaymentEvent($user, $payment, $shopProduct));
+
+ Redirect::route('home')->with('success', 'Your payment is being processed')->send();
+ }
+
+ if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') {
+ $stripeClient->paymentIntents->cancel($paymentIntent->id);
+
+ //redirect back to home
+ Redirect::route('home')->with('info', __('Your payment has been canceled!'))->send();
+ } else {
+ abort(402);
+ }
+ }
+ } catch (Exception $e) {
+ if (env('APP_ENV') == 'local') {
+ dd($e->getMessage());
+ } else {
+ abort(422);
+ }
+ }
+}
+
+/**
+ * @param Request $request
+ */
+function handleStripePaymentSuccessHook($paymentIntent)
+{
+ try {
+ // Get payment db entry
+ $payment = Payment::where('payment_id', $paymentIntent->id)->first();
+ $user = User::where('id', $payment->user_id)->first();
+ $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
+
+ if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
+
+
+ //update payment db entry status
+ $payment->update(['status' => 'paid']);
+
+ //payment notification
+ $user->notify(new ConfirmPaymentNotification($payment));
+ event(new UserUpdateCreditsEvent($user));
+ event(new PaymentEvent($user, $payment, $shopProduct));
+ }
+
+ // return 200
+ return response()->json(['success' => true], 200);
+ } catch (Exception $ex) {
+ abort(422);
+ }
+}
+
+/**
+ * @param Request $request
+ */
+function StripeWebhooks(Request $request)
+{
+ Stripe::setApiKey(getStripeSecret());
+
+ try {
+ $payload = @file_get_contents('php://input');
+ $sig_header = $request->header('Stripe-Signature');
+ $event = null;
+ $event = \Stripe\Webhook::constructEvent(
+ $payload,
+ $sig_header,
+ getStripeEndpointSecret()
+ );
+ } catch (\UnexpectedValueException $e) {
+ // Invalid payload
+
+ abort(400);
+ } catch (SignatureVerificationException $e) {
+ // Invalid signature
+
+ abort(400);
+ }
+
+ // Handle the event
+ switch ($event->type) {
+ case 'payment_intent.succeeded':
+ $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
+ handleStripePaymentSuccessHook($paymentIntent);
+ break;
+ default:
+ echo 'Received unknown event type ' . $event->type;
+ }
+}
+
+/**
+ * @return \Stripe\StripeClient
+ */
+function getStripeClient()
+{
+ return new StripeClient(getStripeSecret());
+}
+
+/**
+ * @return string
+ */
+function getStripeSecret()
+{
+ return env('APP_ENV') == 'local'
+ ? config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET')
+ : config('SETTINGS::PAYMENTS:STRIPE:SECRET');
+}
+
+/**
+ * @return string
+ */
+function getStripeEndpointSecret()
+{
+ return env('APP_ENV') == 'local'
+ ? config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET')
+ : config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET');
+}
+/**
+ * @param $amount
+ * @param $currencyCode
+ * @param $payment_method
+ * @return bool
+ * @description check if the amount is higher than the minimum amount for the stripe gateway
+ */
+function checkPriceAmount($amount, $currencyCode, $payment_method)
+{
+ $minimums = [
+ "USD" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "AED" => [
+ "paypal" => 0,
+ "stripe" => 2
+ ],
+ "AUD" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "BGN" => [
+ "paypal" => 0,
+ "stripe" => 1
+ ],
+ "BRL" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "CAD" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "CHF" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "CZK" => [
+ "paypal" => 0,
+ "stripe" => 15
+ ],
+ "DKK" => [
+ "paypal" => 0,
+ "stripe" => 2.5
+ ],
+ "EUR" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "GBP" => [
+ "paypal" => 0,
+ "stripe" => 0.3
+ ],
+ "HKD" => [
+ "paypal" => 0,
+ "stripe" => 4
+ ],
+ "HRK" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "HUF" => [
+ "paypal" => 0,
+ "stripe" => 175
+ ],
+ "INR" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "JPY" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "MXN" => [
+ "paypal" => 0,
+ "stripe" => 10
+ ],
+ "MYR" => [
+ "paypal" => 0,
+ "stripe" => 2
+ ],
+ "NOK" => [
+ "paypal" => 0,
+ "stripe" => 3
+ ],
+ "NZD" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "PLN" => [
+ "paypal" => 0,
+ "stripe" => 2
+ ],
+ "RON" => [
+ "paypal" => 0,
+ "stripe" => 2
+ ],
+ "SEK" => [
+ "paypal" => 0,
+ "stripe" => 3
+ ],
+ "SGD" => [
+ "paypal" => 0,
+ "stripe" => 0.5
+ ],
+ "THB" => [
+ "paypal" => 0,
+ "stripe" => 10
+ ]
+ ];
+ return $amount >= $minimums[$currencyCode][$payment_method];
+}
+
+function getStripeConfig()
+{
+ return [
+ "name" => "Stripe",
+ "description" => "Stripe payment gateway",
+ "mode" => [
+ "type" => "select",
+ "label" => "Mode",
+ "value" => config("APP_ENV") == 'local' ? "sandbox" : "live",
+ "options" => [
+ "sandbox" => "Sandbox",
+ "live" => "Live",
+ ],
+ ],
+ "TEST_SECRET" => [
+ "type" => "text",
+ "label" => "Test Secret Key",
+ "value" => config("SETTINGS::PAYMENTS:STRIPE:TEST_SECRET"),
+ ],
+ "SECRET" => [
+ "type" => "text",
+ "label" => "Live Secret Key",
+ "value" => config("SETTINGS::PAYMENTS:STRIPE:SECRET"),
+ ],
+ "ENDPOINT_TEST_SECRET" => [
+ "type" => "text",
+ "label" => "Test Endpoint Secret",
+ "value" => config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET"),
+ ],
+ "ENDPOINT_SECRET" => [
+ "type" => "text",
+ "label" => "Live Endpoint Secret",
+ "value" => config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET"),
+ ],
+ ];
+}
diff --git a/app/Extensions/PaymentGateways/Stripe/web_routes.php b/app/Extensions/PaymentGateways/Stripe/web_routes.php
new file mode 100644
index 00000000..adf481da
--- /dev/null
+++ b/app/Extensions/PaymentGateways/Stripe/web_routes.php
@@ -0,0 +1,23 @@
+group(function () {
+ Route::get('payment/StripePay/{shopProduct}', function () {
+ StripePay(request());
+ })->name('payment.StripePay');
+
+ Route::get(
+ 'payment/StripeSuccess',
+ function () {
+ StripeSuccess(request());
+ }
+ )->name('payment.StripeSuccess');
+});
+
+
+// Stripe WebhookRoute -> validation in Route Handler
+Route::post('payment/StripeWebhooks', function () {
+ StripeWebhooks(request());
+})->name('payment.StripeWebhooks');
diff --git a/app/Helpers/ExtensionHelper.php b/app/Helpers/ExtensionHelper.php
new file mode 100644
index 00000000..884b9f2f
--- /dev/null
+++ b/app/Helpers/ExtensionHelper.php
@@ -0,0 +1,47 @@
+name = $config['name'];
+ $payment->image = asset('images/Extensions/PaymentGateways/' . strtolower($extensionName) . '_logo.png');
+ $paymentGateways[] = $payment;
+ }
+ }
+
return view('store.checkout')->with([
'product' => $shopProduct,
'discountpercent' => PartnerDiscount::getDiscount(),
@@ -59,6 +62,7 @@ class PaymentController extends Controller
'taxvalue' => $shopProduct->getTaxValue(),
'taxpercent' => $shopProduct->getTaxPercent(),
'total' => $shopProduct->getTotalPrice(),
+ 'paymentGateways' => $paymentGateways,
]);
}
@@ -67,11 +71,10 @@ class PaymentController extends Controller
* @param ShopProduct $shopProduct
* @return RedirectResponse
*/
- public function FreePay(Request $request, ShopProduct $shopProduct)
+ public function FreePay(ShopProduct $shopProduct)
{
- //dd($shopProduct);
//check if the product is really free or the discount is 100%
- if($shopProduct->getTotalPrice()>0) return redirect()->route('home')->with('error', __('An error ocured. Please try again.'));
+ if ($shopProduct->getTotalPrice() > 0) return redirect()->route('home')->with('error', __('An error ocured. Please try again.'));
//give product
/** @var User $user */
@@ -80,9 +83,9 @@ class PaymentController extends Controller
//not updating server limit
//update User with bought item
- if ($shopProduct->type=="Credits") {
+ if ($shopProduct->type == "Credits") {
$user->increment('credits', $shopProduct->quantity);
- }elseif ($shopProduct->type=="Server slots"){
+ } elseif ($shopProduct->type == "Server slots") {
$user->increment('server_limit', $shopProduct->quantity);
}
@@ -98,7 +101,7 @@ class PaymentController extends Controller
'type' => $shopProduct->type,
'status' => 'paid',
'amount' => $shopProduct->quantity,
- 'price' => $shopProduct->price - ($shopProduct->price*PartnerDiscount::getDiscount()/100),
+ 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
'tax_value' => $shopProduct->getTaxValue(),
'tax_percent' => $shopProduct->getTaxPercent(),
'total_price' => $shopProduct->getTotalPrice(),
@@ -114,196 +117,12 @@ class PaymentController extends Controller
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
}
- /**
- * @param Request $request
- * @param ShopProduct $shopProduct
- * @return RedirectResponse
- */
- public function PaypalPay(Request $request, ShopProduct $shopProduct)
+ public function pay(Request $request)
{
- if(!$this->checkAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), "paypal")) return redirect()->route('home')->with('error', __('The product you chose can´t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'));
- $request = new OrdersCreateRequest();
- $request->prefer('return=representation');
- $request->body = [
- 'intent' => 'CAPTURE',
- 'purchase_units' => [
- [
- 'reference_id' => uniqid(),
- 'description' => $shopProduct->display.(PartnerDiscount::getDiscount() ? (' ('.__('Discount').' '.PartnerDiscount::getDiscount().'%)') : ''),
- 'amount' => [
- 'value' => $shopProduct->getTotalPrice(),
- 'currency_code' => strtoupper($shopProduct->currency_code),
- 'breakdown' => [
- 'item_total' => [
- 'currency_code' => strtoupper($shopProduct->currency_code),
- 'value' => $shopProduct->getPriceAfterDiscount(),
- ],
- 'tax_total' => [
- 'currency_code' => strtoupper($shopProduct->currency_code),
- 'value' => $shopProduct->getTaxValue(),
- ],
- ],
- ],
- ],
- ],
- 'application_context' => [
- 'cancel_url' => route('payment.Cancel'),
- 'return_url' => route('payment.PaypalSuccess', ['product' => $shopProduct->id]),
- 'brand_name' => config('app.name', 'Laravel'),
- 'shipping_preference' => 'NO_SHIPPING',
- ],
+ $product = ShopProduct::find($request->product_id);
+ $paymentGateway = $request->payment_method;
- ];
-
- try {
- // Call API with your client and get a response for your call
- $response = $this->getPayPalClient()->execute($request);
-
- return redirect()->away($response->result->links[1]->href);
-
- // If call returns body in response, you can get the deserialized version from the result attribute of the response
- } catch (HttpException $ex) {
- echo $ex->statusCode;
- dd(json_decode($ex->getMessage()));
- }
- }
-
- /**
- * @return PayPalHttpClient
- */
- protected function getPayPalClient()
- {
- $environment = env('APP_ENV') == 'local'
- ? new SandboxEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret())
- : new ProductionEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret());
-
- return new PayPalHttpClient($environment);
- }
-
- /**
- * @return string
- */
- protected function getPaypalClientId()
- {
- return env('APP_ENV') == 'local' ? config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') : config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID');
- }
-
- /**
- * @return string
- */
- protected function getPaypalClientSecret()
- {
- return env('APP_ENV') == 'local' ? config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') : config('SETTINGS::PAYMENTS:PAYPAL:SECRET');
- }
-
- /**
- * @param Request $laravelRequest
- */
- public function PaypalSuccess(Request $laravelRequest)
- {
- /** @var ShopProduct $shopProduct */
- $shopProduct = ShopProduct::findOrFail($laravelRequest->input('product'));
-
- /** @var User $user */
- $user = Auth::user();
-
- $request = new OrdersCaptureRequest($laravelRequest->input('token'));
- $request->prefer('return=representation');
- try {
- // Call API with your client and get a response for your call
- $response = $this->getPayPalClient()->execute($request);
- if ($response->statusCode == 201 || $response->statusCode == 200) {
-
- //update server limit
- if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
- if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
- $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
- }
- }
-
- //update User with bought item
- if ($shopProduct->type == 'Credits') {
- $user->increment('credits', $shopProduct->quantity);
- } elseif ($shopProduct->type == 'Server slots') {
- $user->increment('server_limit', $shopProduct->quantity);
- }
-
- //give referral commission always
- if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits' && config('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') == 'true') {
- if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
- $ref_user = User::findOrFail($ref_user->referral_id);
- $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, '', '');
- $ref_user->increment('credits', $increment);
-
- //LOGS REFERRALS IN THE ACTIVITY LOG
- activity()
- ->performedOn($user)
- ->causedBy($ref_user)
- ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
- }
- }
-
- //update role give Referral-reward
- if ($user->role == 'member') {
- $user->update(['role' => 'client']);
-
- //give referral commission only on first purchase
- if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits' && config('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') == 'false') {
- if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
- $ref_user = User::findOrFail($ref_user->referral_id);
- $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, '', '');
- $ref_user->increment('credits', $increment);
-
- //LOGS REFERRALS IN THE ACTIVITY LOG
- activity()
- ->performedOn($user)
- ->causedBy($ref_user)
- ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
- }
- }
- }
-
- //store payment
- $payment = Payment::create([
- 'user_id' => $user->id,
- 'payment_id' => $response->result->id,
- 'payment_method' => 'paypal',
- 'type' => $shopProduct->type,
- 'status' => 'paid',
- 'amount' => $shopProduct->quantity,
- 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
- 'tax_value' => $shopProduct->getTaxValue(),
- 'tax_percent' => $shopProduct->getTaxPercent(),
- 'total_price' => $shopProduct->getTotalPrice(),
- 'currency_code' => $shopProduct->currency_code,
- 'shop_item_product_id' => $shopProduct->id,
- ]);
-
- event(new UserUpdateCreditsEvent($user));
-
- //only create invoice if SETTINGS::INVOICE:ENABLED is true
- if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
- $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
- }
-
- //redirect back to home
- return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
- }
-
- // If call returns body in response, you can get the deserialized version from the result attribute of the response
- if (env('APP_ENV') == 'local') {
- dd($response);
- } else {
- abort(500);
- }
- } catch (HttpException $ex) {
- if (env('APP_ENV') == 'local') {
- echo $ex->statusCode;
- dd($ex->getMessage());
- } else {
- abort(422);
- }
- }
+ return redirect()->route('payment.' . $paymentGateway . 'Pay', ['shopProduct' => $product->id]);
}
/**
@@ -311,491 +130,9 @@ class PaymentController extends Controller
*/
public function Cancel(Request $request)
{
- return redirect()->route('store.index')->with('success', 'Payment was Canceled');
+ return redirect()->route('store.index')->with('info', 'Payment was Canceled');
}
- /**
- * @param Request $request
- * @param ShopProduct $shopProduct
- * @return RedirectResponse
- */
- public function StripePay(Request $request, ShopProduct $shopProduct)
- {
- if(!$this->checkAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), "stripe")) return redirect()->route('home')->with('error', __('The product you chose can´t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'));
- $stripeClient = $this->getStripeClient();
-
- $request = $stripeClient->checkout->sessions->create([
- 'line_items' => [
- [
- 'price_data' => [
- 'currency' => $shopProduct->currency_code,
- 'product_data' => [
- 'name' => $shopProduct->display.(PartnerDiscount::getDiscount() ? (' ('.__('Discount').' '.PartnerDiscount::getDiscount().'%)') : ''),
- 'description' => $shopProduct->description,
- ],
- 'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
- ],
- 'quantity' => 1,
- ],
- [
- 'price_data' => [
- 'currency' => $shopProduct->currency_code,
- 'product_data' => [
- 'name' => __('Tax'),
- 'description' => $shopProduct->getTaxPercent().'%',
- ],
- 'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
- ],
- 'quantity' => 1,
- ],
- ],
-
- 'mode' => 'payment',
- 'payment_method_types' => str_getcsv(config('SETTINGS::PAYMENTS:STRIPE:METHODS')),
- 'success_url' => route('payment.StripeSuccess', ['product' => $shopProduct->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 ShopProduct $shopProduct */
- $shopProduct = ShopProduct::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 server limit
- if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
- if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
- $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
- }
- }
-
- //update User with bought item
- if ($shopProduct->type == 'Credits') {
- $user->increment('credits', $shopProduct->quantity);
- } elseif ($shopProduct->type == 'Server slots') {
- $user->increment('server_limit', $shopProduct->quantity);
- }
-
- //update role give Referral-reward
- if ($user->role == 'member') {
- $user->update(['role' => 'client']);
-
- if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits') {
- if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
- $ref_user = User::findOrFail($ref_user->referral_id);
- $increment = number_format($shopProduct->quantity / 100 * config('SETTINGS::REFERRAL:PERCENTAGE'), 0, '', '');
- $ref_user->increment('credits', $increment);
-
- //LOGS REFERRALS IN THE ACTIVITY LOG
- activity()
- ->performedOn($user)
- ->causedBy($ref_user)
- ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
- }
- }
- }
-
- //store paid payment
- $payment = Payment::create([
- 'user_id' => $user->id,
- 'payment_id' => $paymentSession->payment_intent,
- 'payment_method' => 'stripe',
- 'type' => $shopProduct->type,
- 'status' => 'paid',
- 'amount' => $shopProduct->quantity,
- 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
- 'tax_value' => $shopProduct->getTaxValue(),
- 'total_price' => $shopProduct->getTotalPrice(),
- 'tax_percent' => $shopProduct->getTaxPercent(),
- 'currency_code' => $shopProduct->currency_code,
- 'shop_item_product_id' => $shopProduct->id,
- ]);
-
- //payment notification
- $user->notify(new ConfirmPaymentNotification($payment));
-
- event(new UserUpdateCreditsEvent($user));
-
- //only create invoice if SETTINGS::INVOICE:ENABLED is true
- if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
- $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
- }
-
- //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' => $shopProduct->type,
- 'status' => 'processing',
- 'amount' => $shopProduct->quantity,
- 'price' => $shopProduct->price,
- 'tax_value' => $shopProduct->getTaxValue(),
- 'total_price' => $shopProduct->getTotalPrice(),
- 'tax_percent' => $shopProduct->getTaxPercent(),
- 'currency_code' => $shopProduct->currency_code,
- 'shop_item_product_id' => $shopProduct->id,
- ]);
-
- //only create invoice if SETTINGS::INVOICE:ENABLED is true
- if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
- $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
- }
-
- //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') {
-
- //update server limit
- if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
- if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
- $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
- }
- }
- //update User with bought item
- if ($shopProduct->type == 'Credits') {
- $user->increment('credits', $shopProduct->quantity);
- } elseif ($shopProduct->type == 'Server slots') {
- $user->increment('server_limit', $shopProduct->quantity);
- }
-
- //update role give Referral-reward
- if ($user->role == 'member') {
- $user->update(['role' => 'client']);
-
- if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits') {
- if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
- $ref_user = User::findOrFail($ref_user->referral_id);
- $increment = number_format($shopProduct->quantity / 100 * config('SETTINGS::REFERRAL:PERCENTAGE'), 0, '', '');
- $ref_user->increment('credits', $increment);
-
- //LOGS REFERRALS IN THE ACTIVITY LOG
- activity()
- ->performedOn($user)
- ->causedBy($ref_user)
- ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
- }
- }
- }
-
- //update payment db entry status
- $payment->update(['status' => 'paid']);
-
- //payment notification
- $user->notify(new ConfirmPaymentNotification($payment));
- event(new UserUpdateCreditsEvent($user));
-
- //only create invoice if SETTINGS::INVOICE:ENABLED is true
- if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
- $this->createInvoice($user, $payment, 'paid', strtoupper($paymentIntent->currency));
- }
- }
- } 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'
- ? config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET')
- : config('SETTINGS::PAYMENTS:STRIPE:SECRET');
- }
-
- /**
- * @return string
- */
- protected function getStripeEndpointSecret()
- {
- return env('APP_ENV') == 'local'
- ? config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET')
- : config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET');
- }
-
- protected function createInvoice($user, $payment, $paymentStatus, $currencyCode)
- {
- $shopProduct = ShopProduct::where('id', $payment->shop_item_product_id)->first();
- //create invoice
- $lastInvoiceID = \App\Models\Invoice::where('invoice_name', 'like', '%'.now()->format('mY').'%')->count('id');
- $newInvoiceID = $lastInvoiceID + 1;
- $logoPath = storage_path('app/public/logo.png');
-
- $seller = new Party([
- 'name' => config('SETTINGS::INVOICE:COMPANY_NAME'),
- 'phone' => config('SETTINGS::INVOICE:COMPANY_PHONE'),
- 'address' => config('SETTINGS::INVOICE:COMPANY_ADDRESS'),
- 'vat' => config('SETTINGS::INVOICE:COMPANY_VAT'),
- 'custom_fields' => [
- 'E-Mail' => config('SETTINGS::INVOICE:COMPANY_MAIL'),
- 'Web' => config('SETTINGS::INVOICE:COMPANY_WEBSITE'),
- ],
- ]);
-
- $customer = new Buyer([
- 'name' => $user->name,
- 'custom_fields' => [
- 'E-Mail' => $user->email,
- 'Client ID' => $user->id,
- ],
- ]);
- $item = (new InvoiceItem())
- ->title($shopProduct->description)
- ->pricePerUnit($shopProduct->price);
-
- $notes = [
- __('Payment method').': '.$payment->payment_method,
- ];
- $notes = implode('
', $notes);
-
- $invoice = Invoice::make()
- ->template('controlpanel')
- ->name(__('Invoice'))
- ->buyer($customer)
- ->seller($seller)
- ->discountByPercent(PartnerDiscount::getDiscount())
- ->taxRate(floatval($shopProduct->getTaxPercent()))
- ->shipping(0)
- ->addItem($item)
- ->status(__($paymentStatus))
- ->series(now()->format('mY'))
- ->delimiter('-')
- ->sequence($newInvoiceID)
- ->serialNumberFormat(config('SETTINGS::INVOICE:PREFIX').'{DELIMITER}{SERIES}{SEQUENCE}')
- ->currencyCode($currencyCode)
- ->currencySymbol(Currencies::getSymbol($currencyCode))
- ->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));
- }
-
- public function checkAmount($amount, $currencyCode, $payment_method)
- {
- $minimums = [
- "USD" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "AED" => [
- "paypal" => 0,
- "stripe" => 2
- ],
- "AUD" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "BGN" => [
- "paypal" => 0,
- "stripe" => 1
- ],
- "BRL" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "CAD" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "CHF" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "CZK" => [
- "paypal" => 0,
- "stripe" => 15
- ],
- "DKK" => [
- "paypal" => 0,
- "stripe" => 2.5
- ],
- "EUR" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "GBP" => [
- "paypal" => 0,
- "stripe" => 0.3
- ],
- "HKD" => [
- "paypal" => 0,
- "stripe" => 4
- ],
- "HRK" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "HUF" => [
- "paypal" => 0,
- "stripe" => 175
- ],
- "INR" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "JPY" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "MXN" => [
- "paypal" => 0,
- "stripe" => 10
- ],
- "MYR" => [
- "paypal" => 0,
- "stripe" => 2
- ],
- "NOK" => [
- "paypal" => 0,
- "stripe" => 3
- ],
- "NZD" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "PLN" => [
- "paypal" => 0,
- "stripe" => 2
- ],
- "RON" => [
- "paypal" => 0,
- "stripe" => 2
- ],
- "SEK" => [
- "paypal" => 0,
- "stripe" => 3
- ],
- "SGD" => [
- "paypal" => 0,
- "stripe" => 0.5
- ],
- "THB" => [
- "paypal" => 0,
- "stripe" => 10
- ]
- ];
- return $amount >= $minimums[$currencyCode][$payment_method];
- }
-
-
/**
* @return JsonResponse|mixed
*
@@ -808,9 +145,7 @@ class PaymentController extends Controller
return datatables($query)
->addColumn('user', function (Payment $payment) {
- return
- ($payment->user)?''.$payment->user->name.'':__('Unknown user');
-
+ return ($payment->user) ? '' . $payment->user->name . '' : __('Unknown user');
})
->editColumn('price', function (Payment $payment) {
return $payment->formatToCurrency($payment->price);
@@ -819,18 +154,20 @@ class PaymentController extends Controller
return $payment->formatToCurrency($payment->tax_value);
})
->editColumn('tax_percent', function (Payment $payment) {
- return $payment->tax_percent.' %';
+ return $payment->tax_percent . ' %';
})
->editColumn('total_price', function (Payment $payment) {
return $payment->formatToCurrency($payment->total_price);
})
->editColumn('created_at', function (Payment $payment) {
- return ['display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
- 'raw' => $payment->created_at ? strtotime($payment->created_at) : ''];
+ return [
+ 'display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
+ 'raw' => $payment->created_at ? strtotime($payment->created_at) : ''
+ ];
})
->addColumn('actions', function (Payment $payment) {
- return '';
+ return '';
})
->rawColumns(['actions', 'user'])
->make(true);
diff --git a/app/Listeners/CreateInvoice.php b/app/Listeners/CreateInvoice.php
new file mode 100644
index 00000000..08d772c0
--- /dev/null
+++ b/app/Listeners/CreateInvoice.php
@@ -0,0 +1,31 @@
+payment->user;
+
+ // create invoice using the trait
+ $this->createInvoice($user, $event->payment);
+ }
+ }
+}
diff --git a/app/Listeners/UserPayment.php b/app/Listeners/UserPayment.php
new file mode 100644
index 00000000..be947087
--- /dev/null
+++ b/app/Listeners/UserPayment.php
@@ -0,0 +1,82 @@
+user;
+ $shopProduct = $event->shopProduct;
+
+ // only update user if payment is paid
+ if ($event->payment->status != "paid") {
+ return;
+ }
+
+ //update server limit
+ if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0 && $user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
+ $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
+ }
+
+ //update User with bought item
+ if ($shopProduct->type == "Credits") {
+ $user->increment('credits', $shopProduct->quantity);
+ } elseif ($shopProduct->type == "Server slots") {
+ $user->increment('server_limit', $shopProduct->quantity);
+ }
+
+ //give referral commission always
+ if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "true") {
+ if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
+ $ref_user = User::findOrFail($ref_user->referral_id);
+ $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
+ $ref_user->increment('credits', $increment);
+
+ //LOGS REFERRALS IN THE ACTIVITY LOG
+ activity()
+ ->performedOn($user)
+ ->causedBy($ref_user)
+ ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
+ }
+ }
+ //update role give Referral-reward
+ if ($user->role == 'member') {
+ $user->update(['role' => 'client']);
+
+ //give referral commission only on first purchase
+ if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "false") {
+ if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
+ $ref_user = User::findOrFail($ref_user->referral_id);
+ $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
+ $ref_user->increment('credits', $increment);
+
+ //LOGS REFERRALS IN THE ACTIVITY LOG
+ activity()
+ ->performedOn($user)
+ ->causedBy($ref_user)
+ ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
+ }
+ }
+ }
+
+ // LOGS PAYMENT IN THE ACTIVITY LOG
+ activity()
+ ->performedOn($user)
+ ->causedBy($user)
+ ->log('bought ' . $shopProduct->quantity . ' ' . $shopProduct->type . ' for ' . $shopProduct->price . $shopProduct->currency_code);
+ }
+}
diff --git a/app/Models/Payment.php b/app/Models/Payment.php
index ac281d5e..04c32831 100644
--- a/app/Models/Payment.php
+++ b/app/Models/Payment.php
@@ -7,20 +7,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use NumberFormatter;
-use Spatie\Activitylog\LogOptions;
-use Spatie\Activitylog\Traits\LogsActivity;
class Payment extends Model
{
use HasFactory;
- use LogsActivity;
- public function getActivitylogOptions(): LogOptions
- {
- return LogOptions::defaults()
- -> logOnlyDirty()
- -> logOnly(['*'])
- -> dontSubmitEmptyLogs();
- }
+
public $incrementing = false;
/**
diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php
index cc8427ff..bdd71a3a 100644
--- a/app/Providers/EventServiceProvider.php
+++ b/app/Providers/EventServiceProvider.php
@@ -2,8 +2,11 @@
namespace App\Providers;
+use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
+use App\Listeners\CreateInvoice;
use App\Listeners\UnsuspendServers;
+use App\Listeners\UserPayment;
use App\Listeners\Verified;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
@@ -24,6 +27,10 @@ class EventServiceProvider extends ServiceProvider
UserUpdateCreditsEvent::class => [
UnsuspendServers::class,
],
+ PaymentEvent::class => [
+ CreateInvoice::class,
+ UserPayment::class,
+ ],
SocialiteWasCalled::class => [
// ... other providers
'SocialiteProviders\\Discord\\DiscordExtendSocialite@handle',
diff --git a/app/Traits/Invoiceable.php b/app/Traits/Invoiceable.php
new file mode 100644
index 00000000..c9073d36
--- /dev/null
+++ b/app/Traits/Invoiceable.php
@@ -0,0 +1,91 @@
+shop_item_product_id)->first();
+ //create invoice
+ $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
+ $newInvoiceID = $lastInvoiceID + 1;
+ $logoPath = storage_path('app/public/logo.png');
+
+ $seller = new Party([
+ 'name' => config("SETTINGS::INVOICE:COMPANY_NAME"),
+ 'phone' => config("SETTINGS::INVOICE:COMPANY_PHONE"),
+ 'address' => config("SETTINGS::INVOICE:COMPANY_ADDRESS"),
+ 'vat' => config("SETTINGS::INVOICE:COMPANY_VAT"),
+ 'custom_fields' => [
+ 'E-Mail' => config("SETTINGS::INVOICE:COMPANY_MAIL"),
+ "Web" => config("SETTINGS::INVOICE:COMPANY_WEBSITE")
+ ],
+ ]);
+
+
+ $customer = new Buyer([
+ 'name' => $user->name,
+ 'custom_fields' => [
+ 'E-Mail' => $user->email,
+ 'Client ID' => $user->id,
+ ],
+ ]);
+ $item = (new InvoiceItem())
+ ->title($shopProduct->description)
+ ->pricePerUnit($shopProduct->price);
+
+ $notes = [
+ __("Payment method") . ": " . $payment->payment_method,
+ ];
+ $notes = implode("
", $notes);
+
+
+ $invoice = Invoice::make()
+ ->template('controlpanel')
+ ->name(__("Invoice"))
+ ->buyer($customer)
+ ->seller($seller)
+ ->discountByPercent(PartnerDiscount::getDiscount())
+ ->taxRate(floatval($shopProduct->getTaxPercent()))
+ ->shipping(0)
+ ->addItem($item)
+ ->status(__($payment->status))
+ ->series(now()->format('mY'))
+ ->delimiter("-")
+ ->sequence($newInvoiceID)
+ ->serialNumberFormat(config("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
+ ->currencyCode(strtoupper($payment->currency_code))
+ ->currencySymbol(Currencies::getSymbol(strtoupper($payment->currency_code)))
+ ->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));
+ }
+}
diff --git a/public/images/paypal_logo.png b/public/images/Extensions/PaymentGateways/paypal_logo.png
similarity index 100%
rename from public/images/paypal_logo.png
rename to public/images/Extensions/PaymentGateways/paypal_logo.png
diff --git a/public/images/stripe_logo.png b/public/images/Extensions/PaymentGateways/stripe_logo.png
similarity index 100%
rename from public/images/stripe_logo.png
rename to public/images/Extensions/PaymentGateways/stripe_logo.png
diff --git a/routes/api.php b/routes/api.php
index 0de04de6..74333b74 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -34,6 +34,8 @@ Route::middleware('api.token')->group(function () {
Route::get('/notifications/{user}', [NotificationController::class, 'index']);
Route::get('/notifications/{user}/{notification}', [NotificationController::class, 'view']);
Route::post('/notifications', [NotificationController::class, 'send']);
- Route::delete('/notifications/{user}', [NotificationController::class, 'delete']);
Route::delete('/notifications/{user}/{notification}', [NotificationController::class, 'deleteOne']);
+ Route::delete('/notifications/{user}', [NotificationController::class, 'delete']);
});
+
+require __DIR__ . '/extensions_api.php';
diff --git a/routes/extensions_api.php b/routes/extensions_api.php
new file mode 100644
index 00000000..31fb89d3
--- /dev/null
+++ b/routes/extensions_api.php
@@ -0,0 +1,21 @@
+ 'extensions', 'middleware' => 'api.token'], function () {
+ // get all extensions that are inside App/Extensions
+ // It is important that the extensions are inside a folder with the name of the extension
+ // while those folders are inside Folders with the name of the type of extension like PaymentGateways, Themes, etc.
+ $extensionNamespaces = glob(app_path() . '/Extensions/*', GLOB_ONLYDIR);
+ $extensions = [];
+ foreach ($extensionNamespaces as $extensionNamespace) {
+ $extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR));
+ }
+
+ foreach ($extensions as $extension) {
+ $routesFile = $extension . '/api_routes.php';
+ if (file_exists($routesFile)) {
+ include_once $routesFile;
+ }
+ }
+});
diff --git a/routes/extensions_web.php b/routes/extensions_web.php
new file mode 100644
index 00000000..920dc299
--- /dev/null
+++ b/routes/extensions_web.php
@@ -0,0 +1,22 @@
+ 'extensions'], function () {
+
+ // get all extensions that are inside App/Extensions
+ // It is important that the extensions are inside a folder with the name of the extension
+ // while those folders are inside Folders with the name of the type of extension like PaymentGateways, Themes, etc.
+ $extensionNamespaces = glob(app_path() . '/Extensions/*', GLOB_ONLYDIR);
+ $extensions = [];
+ foreach ($extensionNamespaces as $extensionNamespace) {
+ $extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR));
+ }
+
+ foreach ($extensions as $extension) {
+ $routesFile = $extension . '/web_routes.php';
+ if (file_exists($routesFile)) {
+ include_once $routesFile;
+ }
+ }
+});
diff --git a/routes/web.php b/routes/web.php
index 27c07c74..9c873ad1 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -49,17 +49,14 @@ 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::get('/privacy', function () {
-return view('information.privacy');
+ return view('information.privacy');
})->name('privacy');
Route::get('/imprint', function () {
-return view('information.imprint');
+ return view('information.imprint');
})->name('imprint');
Route::get('/tos', function () {
-return view('information.tos');
+ return view('information.tos');
})->name('tos');
Route::middleware(['auth', 'checkSuspended'])->group(function () {
@@ -90,10 +87,7 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
//payments
Route::get('checkout/{shopProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
- Route::get('payment/PaypalPay/{shopProduct}', [PaymentController::class, 'PaypalPay'])->name('payment.PaypalPay');
- Route::get('payment/PaypalSuccess', [PaymentController::class, 'PaypalSuccess'])->name('payment.PaypalSuccess');
- Route::get('payment/StripePay/{shopProduct}', [PaymentController::class, 'StripePay'])->name('payment.StripePay');
- Route::get('payment/StripeSuccess', [PaymentController::class, 'StripeSuccess'])->name('payment.StripeSuccess');
+ Route::post('payment/pay', [PaymentController::class, 'pay'])->name('payment.pay');
Route::get('payment/FreePay/{shopProduct}', [PaymentController::class, 'FreePay'])->name('payment.FreePay');
Route::get('payment/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
@@ -221,3 +215,5 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
Route::get('/home', [HomeController::class, 'index'])->name('home');
});
+
+require __DIR__ . '/extensions_web.php';
diff --git a/themes/default/views/store/checkout.blade.php b/themes/default/views/store/checkout.blade.php
index 2e0556ca..cab3d937 100644
--- a/themes/default/views/store/checkout.blade.php
+++ b/themes/default/views/store/checkout.blade.php
@@ -10,8 +10,7 @@