[FEATURE] Extension Support & Payment Gateways as Extensions 🔥
[FEATURE] Extension Support & Payment Gateways as Extensions 🔥
This commit is contained in:
commit
7a91013bd4
31
app/Events/PaymentEvent.php
Normal file
31
app/Events/PaymentEvent.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\ShopProduct;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class PaymentEvent
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
public User $user;
|
||||||
|
public Payment $payment;
|
||||||
|
public ShopProduct $shopProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, Payment $payment, ShopProduct $shopProduct)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->payment = $payment;
|
||||||
|
$this->shopProduct = $shopProduct;
|
||||||
|
}
|
||||||
|
}
|
216
app/Extensions/PaymentGateways/PayPal/index.php
Normal file
216
app/Extensions/PaymentGateways/PayPal/index.php
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Events\PaymentEvent;
|
||||||
|
use App\Events\UserUpdateCreditsEvent;
|
||||||
|
use App\Models\PartnerDiscount;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\ShopProduct;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
||||||
|
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
||||||
|
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
||||||
|
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
||||||
|
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
||||||
|
use PayPalHttp\HttpException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param ShopProduct $shopProduct
|
||||||
|
*/
|
||||||
|
function PaypalPay(Request $request)
|
||||||
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = Auth::user();
|
||||||
|
$shopProduct = ShopProduct::findOrFail($request->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"),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
18
app/Extensions/PaymentGateways/PayPal/web_routes.php
Normal file
18
app/Extensions/PaymentGateways/PayPal/web_routes.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
include_once(__DIR__ . '/index.php');
|
||||||
|
|
||||||
|
Route::middleware(['web', 'auth'])->group(function () {
|
||||||
|
Route::get('payment/PayPalPay/{shopProduct}', function () {
|
||||||
|
PaypalPay(request());
|
||||||
|
})->name('payment.PayPalPay');
|
||||||
|
|
||||||
|
Route::get(
|
||||||
|
'payment/PayPalSuccess',
|
||||||
|
function () {
|
||||||
|
PaypalSuccess(request());
|
||||||
|
}
|
||||||
|
)->name('payment.PayPalSuccess');
|
||||||
|
});
|
402
app/Extensions/PaymentGateways/Stripe/index.php
Normal file
402
app/Extensions/PaymentGateways/Stripe/index.php
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Events\PaymentEvent;
|
||||||
|
use App\Events\UserUpdateCreditsEvent;
|
||||||
|
use App\Models\PartnerDiscount;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\ShopProduct;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Notifications\ConfirmPaymentNotification;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
use Stripe\Exception\SignatureVerificationException;
|
||||||
|
use Stripe\Stripe;
|
||||||
|
use Stripe\StripeClient;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param ShopProduct $shopProduct
|
||||||
|
*/
|
||||||
|
function StripePay(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
$shopProduct = ShopProduct::findOrFail($request->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"),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
23
app/Extensions/PaymentGateways/Stripe/web_routes.php
Normal file
23
app/Extensions/PaymentGateways/Stripe/web_routes.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
include_once(__DIR__ . '/index.php');
|
||||||
|
Route::middleware(['web', 'auth'])->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');
|
47
app/Helpers/ExtensionHelper.php
Normal file
47
app/Helpers/ExtensionHelper.php
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
class ExtensionHelper
|
||||||
|
{
|
||||||
|
public static function getExtensionConfig($extensionName, $nameSpace)
|
||||||
|
{
|
||||||
|
$extension = app_path() . '/Extensions/' . $nameSpace . "/" . $extensionName . "/index.php";
|
||||||
|
// Check if extension exists
|
||||||
|
if (!file_exists($extension)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the getConfig function from the index.php file of the extension
|
||||||
|
$config = include_once $extension;
|
||||||
|
|
||||||
|
// Check if the getConfig function exists
|
||||||
|
if (!function_exists('get' . $extensionName . 'Config')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = call_user_func('get' . $extensionName . 'Config');
|
||||||
|
|
||||||
|
// Check if the getConfig function returned an array
|
||||||
|
if (!is_array($config)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getPayMethod($extensionName, $nameSpace)
|
||||||
|
{
|
||||||
|
// return the payment method of the extension to be used elsewhere
|
||||||
|
// for example in the payment controller
|
||||||
|
// the function starts with the name of the extension and ends with Pay
|
||||||
|
|
||||||
|
$config = self::getExtensionConfig($extensionName, $nameSpace);
|
||||||
|
|
||||||
|
if ($config == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $config['payMethod'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,8 @@ use App\Events\UserUpdateCreditsEvent;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\PartnerDiscount;
|
use App\Models\PartnerDiscount;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\ShopProduct;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Notifications\ConfirmPaymentNotification;
|
use App\Models\ShopProduct;
|
||||||
use App\Notifications\InvoiceNotification;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
|
@ -18,19 +16,8 @@ use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use App\Helpers\ExtensionHelper;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use LaravelDaily\Invoices\Classes\Buyer;
|
|
||||||
use LaravelDaily\Invoices\Classes\InvoiceItem;
|
|
||||||
use LaravelDaily\Invoices\Classes\Party;
|
|
||||||
use LaravelDaily\Invoices\Invoice;
|
|
||||||
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
|
||||||
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
|
||||||
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
|
||||||
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
|
||||||
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
|
||||||
use PayPalHttp\HttpException;
|
|
||||||
use Symfony\Component\Intl\Currencies;
|
|
||||||
|
|
||||||
class PaymentController extends Controller
|
class PaymentController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -49,8 +36,24 @@ class PaymentController extends Controller
|
||||||
* @param ShopProduct $shopProduct
|
* @param ShopProduct $shopProduct
|
||||||
* @return Application|Factory|View
|
* @return Application|Factory|View
|
||||||
*/
|
*/
|
||||||
public function checkOut(Request $request, ShopProduct $shopProduct)
|
public function checkOut(ShopProduct $shopProduct)
|
||||||
{
|
{
|
||||||
|
// get all payment gateway extensions
|
||||||
|
$extensions = glob(app_path() . '/Extensions/PaymentGateways/*', GLOB_ONLYDIR);
|
||||||
|
|
||||||
|
// build a paymentgateways array that contains the routes for the payment gateways and the image path for the payment gateway which lays in public/images/Extensions/PaymentGateways with the extensionname in lowercase
|
||||||
|
$paymentGateways = [];
|
||||||
|
foreach ($extensions as $extension) {
|
||||||
|
$extensionName = basename($extension);
|
||||||
|
$config = ExtensionHelper::getExtensionConfig($extensionName, 'PaymentGateways');
|
||||||
|
if ($config) {
|
||||||
|
$payment = new \stdClass();
|
||||||
|
$payment->name = $config['name'];
|
||||||
|
$payment->image = asset('images/Extensions/PaymentGateways/' . strtolower($extensionName) . '_logo.png');
|
||||||
|
$paymentGateways[] = $payment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return view('store.checkout')->with([
|
return view('store.checkout')->with([
|
||||||
'product' => $shopProduct,
|
'product' => $shopProduct,
|
||||||
'discountpercent' => PartnerDiscount::getDiscount(),
|
'discountpercent' => PartnerDiscount::getDiscount(),
|
||||||
|
@ -59,6 +62,7 @@ class PaymentController extends Controller
|
||||||
'taxvalue' => $shopProduct->getTaxValue(),
|
'taxvalue' => $shopProduct->getTaxValue(),
|
||||||
'taxpercent' => $shopProduct->getTaxPercent(),
|
'taxpercent' => $shopProduct->getTaxPercent(),
|
||||||
'total' => $shopProduct->getTotalPrice(),
|
'total' => $shopProduct->getTotalPrice(),
|
||||||
|
'paymentGateways' => $paymentGateways,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,11 +71,10 @@ class PaymentController extends Controller
|
||||||
* @param ShopProduct $shopProduct
|
* @param ShopProduct $shopProduct
|
||||||
* @return RedirectResponse
|
* @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%
|
//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
|
//give product
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
|
@ -80,9 +83,9 @@ class PaymentController extends Controller
|
||||||
//not updating server limit
|
//not updating server limit
|
||||||
|
|
||||||
//update User with bought item
|
//update User with bought item
|
||||||
if ($shopProduct->type=="Credits") {
|
if ($shopProduct->type == "Credits") {
|
||||||
$user->increment('credits', $shopProduct->quantity);
|
$user->increment('credits', $shopProduct->quantity);
|
||||||
}elseif ($shopProduct->type=="Server slots"){
|
} elseif ($shopProduct->type == "Server slots") {
|
||||||
$user->increment('server_limit', $shopProduct->quantity);
|
$user->increment('server_limit', $shopProduct->quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ class PaymentController extends Controller
|
||||||
'type' => $shopProduct->type,
|
'type' => $shopProduct->type,
|
||||||
'status' => 'paid',
|
'status' => 'paid',
|
||||||
'amount' => $shopProduct->quantity,
|
'amount' => $shopProduct->quantity,
|
||||||
'price' => $shopProduct->price - ($shopProduct->price*PartnerDiscount::getDiscount()/100),
|
'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
|
||||||
'tax_value' => $shopProduct->getTaxValue(),
|
'tax_value' => $shopProduct->getTaxValue(),
|
||||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||||
'total_price' => $shopProduct->getTotalPrice(),
|
'total_price' => $shopProduct->getTotalPrice(),
|
||||||
|
@ -114,196 +117,12 @@ class PaymentController extends Controller
|
||||||
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
|
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function pay(Request $request)
|
||||||
* @param Request $request
|
|
||||||
* @param ShopProduct $shopProduct
|
|
||||||
* @return RedirectResponse
|
|
||||||
*/
|
|
||||||
public function PaypalPay(Request $request, ShopProduct $shopProduct)
|
|
||||||
{
|
{
|
||||||
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.'));
|
$product = ShopProduct::find($request->product_id);
|
||||||
$request = new OrdersCreateRequest();
|
$paymentGateway = $request->payment_method;
|
||||||
$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',
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
return redirect()->route('payment.' . $paymentGateway . 'Pay', ['shopProduct' => $product->id]);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -311,491 +130,9 @@ class PaymentController extends Controller
|
||||||
*/
|
*/
|
||||||
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('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('<br>', $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
|
* @return JsonResponse|mixed
|
||||||
*
|
*
|
||||||
|
@ -808,9 +145,7 @@ class PaymentController extends Controller
|
||||||
return datatables($query)
|
return datatables($query)
|
||||||
|
|
||||||
->addColumn('user', function (Payment $payment) {
|
->addColumn('user', function (Payment $payment) {
|
||||||
return
|
return ($payment->user) ? '<a href="' . route('admin.users.show', $payment->user->id) . '">' . $payment->user->name . '</a>' : __('Unknown user');
|
||||||
($payment->user)?'<a href="'.route('admin.users.show', $payment->user->id).'">'.$payment->user->name.'</a>':__('Unknown user');
|
|
||||||
|
|
||||||
})
|
})
|
||||||
->editColumn('price', function (Payment $payment) {
|
->editColumn('price', function (Payment $payment) {
|
||||||
return $payment->formatToCurrency($payment->price);
|
return $payment->formatToCurrency($payment->price);
|
||||||
|
@ -819,18 +154,20 @@ class PaymentController extends Controller
|
||||||
return $payment->formatToCurrency($payment->tax_value);
|
return $payment->formatToCurrency($payment->tax_value);
|
||||||
})
|
})
|
||||||
->editColumn('tax_percent', function (Payment $payment) {
|
->editColumn('tax_percent', function (Payment $payment) {
|
||||||
return $payment->tax_percent.' %';
|
return $payment->tax_percent . ' %';
|
||||||
})
|
})
|
||||||
->editColumn('total_price', function (Payment $payment) {
|
->editColumn('total_price', function (Payment $payment) {
|
||||||
return $payment->formatToCurrency($payment->total_price);
|
return $payment->formatToCurrency($payment->total_price);
|
||||||
})
|
})
|
||||||
|
|
||||||
->editColumn('created_at', function (Payment $payment) {
|
->editColumn('created_at', function (Payment $payment) {
|
||||||
return ['display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
|
return [
|
||||||
'raw' => $payment->created_at ? strtotime($payment->created_at) : ''];
|
'display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
|
||||||
|
'raw' => $payment->created_at ? strtotime($payment->created_at) : ''
|
||||||
|
];
|
||||||
})
|
})
|
||||||
->addColumn('actions', function (Payment $payment) {
|
->addColumn('actions', function (Payment $payment) {
|
||||||
return '<a data-content="'.__('Download').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.invoices.downloadSingleInvoice', 'id='.$payment->payment_id).'" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>';
|
return '<a data-content="' . __('Download') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.invoices.downloadSingleInvoice', 'id=' . $payment->payment_id) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>';
|
||||||
})
|
})
|
||||||
->rawColumns(['actions', 'user'])
|
->rawColumns(['actions', 'user'])
|
||||||
->make(true);
|
->make(true);
|
||||||
|
|
31
app/Listeners/CreateInvoice.php
Normal file
31
app/Listeners/CreateInvoice.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\PaymentEvent;
|
||||||
|
use App\Traits\Invoiceable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
|
||||||
|
class CreateInvoice implements ShouldQueue
|
||||||
|
{
|
||||||
|
|
||||||
|
use Invoiceable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\PaymentEvent $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(PaymentEvent $event)
|
||||||
|
{
|
||||||
|
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||||
|
// get user from payment which does hold the user_id
|
||||||
|
$user = $event->payment->user;
|
||||||
|
|
||||||
|
// create invoice using the trait
|
||||||
|
$this->createInvoice($user, $event->payment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
app/Listeners/UserPayment.php
Normal file
82
app/Listeners/UserPayment.php
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\PaymentEvent;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use App\Models\PartnerDiscount;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
|
||||||
|
class UserPayment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\PaymentEvent $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(PaymentEvent $event)
|
||||||
|
{
|
||||||
|
$user = $event->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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,20 +7,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use NumberFormatter;
|
use NumberFormatter;
|
||||||
use Spatie\Activitylog\LogOptions;
|
|
||||||
use Spatie\Activitylog\Traits\LogsActivity;
|
|
||||||
|
|
||||||
class Payment extends Model
|
class Payment extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
use LogsActivity;
|
|
||||||
public function getActivitylogOptions(): LogOptions
|
|
||||||
{
|
|
||||||
return LogOptions::defaults()
|
|
||||||
-> logOnlyDirty()
|
|
||||||
-> logOnly(['*'])
|
|
||||||
-> dontSubmitEmptyLogs();
|
|
||||||
}
|
|
||||||
public $incrementing = false;
|
public $incrementing = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Events\PaymentEvent;
|
||||||
use App\Events\UserUpdateCreditsEvent;
|
use App\Events\UserUpdateCreditsEvent;
|
||||||
|
use App\Listeners\CreateInvoice;
|
||||||
use App\Listeners\UnsuspendServers;
|
use App\Listeners\UnsuspendServers;
|
||||||
|
use App\Listeners\UserPayment;
|
||||||
use App\Listeners\Verified;
|
use App\Listeners\Verified;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
|
@ -24,6 +27,10 @@ class EventServiceProvider extends ServiceProvider
|
||||||
UserUpdateCreditsEvent::class => [
|
UserUpdateCreditsEvent::class => [
|
||||||
UnsuspendServers::class,
|
UnsuspendServers::class,
|
||||||
],
|
],
|
||||||
|
PaymentEvent::class => [
|
||||||
|
CreateInvoice::class,
|
||||||
|
UserPayment::class,
|
||||||
|
],
|
||||||
SocialiteWasCalled::class => [
|
SocialiteWasCalled::class => [
|
||||||
// ... other providers
|
// ... other providers
|
||||||
'SocialiteProviders\\Discord\\DiscordExtendSocialite@handle',
|
'SocialiteProviders\\Discord\\DiscordExtendSocialite@handle',
|
||||||
|
|
91
app/Traits/Invoiceable.php
Normal file
91
app/Traits/Invoiceable.php
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Models\PartnerDiscount;
|
||||||
|
use App\Models\ShopProduct;
|
||||||
|
use App\Notifications\InvoiceNotification;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use LaravelDaily\Invoices\Classes\Buyer;
|
||||||
|
use LaravelDaily\Invoices\Classes\InvoiceItem;
|
||||||
|
use LaravelDaily\Invoices\Classes\Party;
|
||||||
|
use LaravelDaily\Invoices\Invoice;
|
||||||
|
use Symfony\Component\Intl\Currencies;
|
||||||
|
|
||||||
|
trait Invoiceable
|
||||||
|
{
|
||||||
|
public function createInvoice($user, $payment)
|
||||||
|
{
|
||||||
|
$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("<br>", $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));
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
@ -34,6 +34,8 @@ Route::middleware('api.token')->group(function () {
|
||||||
Route::get('/notifications/{user}', [NotificationController::class, 'index']);
|
Route::get('/notifications/{user}', [NotificationController::class, 'index']);
|
||||||
Route::get('/notifications/{user}/{notification}', [NotificationController::class, 'view']);
|
Route::get('/notifications/{user}/{notification}', [NotificationController::class, 'view']);
|
||||||
Route::post('/notifications', [NotificationController::class, 'send']);
|
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}/{notification}', [NotificationController::class, 'deleteOne']);
|
||||||
|
Route::delete('/notifications/{user}', [NotificationController::class, 'delete']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
require __DIR__ . '/extensions_api.php';
|
||||||
|
|
21
routes/extensions_api.php
Normal file
21
routes/extensions_api.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::group(['prefix' => '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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
22
routes/extensions_web.php
Normal file
22
routes/extensions_web.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::group(['prefix' => '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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -49,17 +49,14 @@ Route::middleware('guest')->get('/', function () {
|
||||||
|
|
||||||
Auth::routes(['verify' => true]);
|
Auth::routes(['verify' => true]);
|
||||||
|
|
||||||
// Stripe WebhookRoute -> validation in Route Handler
|
|
||||||
Route::post('payment/StripeWebhooks', [PaymentController::class, 'StripeWebhooks'])->name('payment.StripeWebhooks');
|
|
||||||
|
|
||||||
Route::get('/privacy', function () {
|
Route::get('/privacy', function () {
|
||||||
return view('information.privacy');
|
return view('information.privacy');
|
||||||
})->name('privacy');
|
})->name('privacy');
|
||||||
Route::get('/imprint', function () {
|
Route::get('/imprint', function () {
|
||||||
return view('information.imprint');
|
return view('information.imprint');
|
||||||
})->name('imprint');
|
})->name('imprint');
|
||||||
Route::get('/tos', function () {
|
Route::get('/tos', function () {
|
||||||
return view('information.tos');
|
return view('information.tos');
|
||||||
})->name('tos');
|
})->name('tos');
|
||||||
|
|
||||||
Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
|
@ -90,10 +87,7 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
|
|
||||||
//payments
|
//payments
|
||||||
Route::get('checkout/{shopProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
|
Route::get('checkout/{shopProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
|
||||||
Route::get('payment/PaypalPay/{shopProduct}', [PaymentController::class, 'PaypalPay'])->name('payment.PaypalPay');
|
Route::post('payment/pay', [PaymentController::class, 'pay'])->name('payment.pay');
|
||||||
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::get('payment/FreePay/{shopProduct}', [PaymentController::class, 'FreePay'])->name('payment.FreePay');
|
Route::get('payment/FreePay/{shopProduct}', [PaymentController::class, 'FreePay'])->name('payment.FreePay');
|
||||||
Route::get('payment/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
|
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');
|
Route::get('/home', [HomeController::class, 'index'])->name('home');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
require __DIR__ . '/extensions_web.php';
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<ol class="breadcrumb float-sm-right">
|
<ol class="breadcrumb float-sm-right">
|
||||||
<li class="breadcrumb-item"><a class=""
|
<li class="breadcrumb-item"><a class="" href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
|
||||||
href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
|
|
||||||
<li class="breadcrumb-item"><a class="text-muted"
|
<li class="breadcrumb-item"><a class="text-muted"
|
||||||
href="{{ route('store.index') }}">{{ __('Store') }}</a>
|
href="{{ route('store.index') }}">{{ __('Store') }}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -23,13 +22,15 @@
|
||||||
<!-- END CONTENT HEADER -->
|
<!-- END CONTENT HEADER -->
|
||||||
|
|
||||||
<!-- MAIN CONTENT -->
|
<!-- MAIN CONTENT -->
|
||||||
<section x-data="serverApp()" x-init="$watch('paymentMethod', value => setPaymentRoute(value))" class="content">
|
<section class="content">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
||||||
|
<form x-data="{ payment_method: '', clicked: false }" action="{{ route('payment.pay') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@method('post')
|
||||||
<!-- Main content -->
|
<!-- Main content -->
|
||||||
<div class="invoice p-3 mb-3">
|
<div class="invoice p-3 mb-3">
|
||||||
<!-- title row -->
|
<!-- title row -->
|
||||||
|
@ -67,6 +68,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<input type="hidden" name="product_id" value="{{ $product->id }}">
|
||||||
</div>
|
</div>
|
||||||
<!-- /.col -->
|
<!-- /.col -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,33 +77,22 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- accepted payments column -->
|
<!-- accepted payments column -->
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
@if($total!=0)
|
|
||||||
<p class="lead">{{ __('Payment Methods') }}:</p>
|
<p class="lead">{{ __('Payment Methods') }}:</p>
|
||||||
|
|
||||||
<div>
|
<div class="d-flex flex-wrap flex-direction-row">
|
||||||
@if (config('SETTINGS::PAYMENTS:PAYPAL:SECRET') || config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET'))
|
@foreach ($paymentGateways as $gateway)
|
||||||
<label class="text-center " for="paypal">
|
<div class="ml-2">
|
||||||
<img class="mb-3" height="50"
|
<label class="text-center" for="{{ $gateway->name }}">
|
||||||
src="{{ url('/images/paypal_logo.png') }}"></br>
|
<img class="mb-3" height="50" src="{{ $gateway->image }}"></br>
|
||||||
|
<input x-on:click="console.log(payment_method)" x-model="payment_method"
|
||||||
<input x-model="paymentMethod" type="radio" id="paypal" value="paypal"
|
type="radio" id="{{ $gateway->name }}"
|
||||||
name="payment_method">
|
value="{{ $gateway->name }}">
|
||||||
</input>
|
</input>
|
||||||
</label>
|
</label>
|
||||||
@endif
|
|
||||||
@if (config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') || config('SETTINGS::PAYMENTS: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>
|
</div>
|
||||||
@else
|
@endforeach
|
||||||
<p class="lead" style="text-align: center">{{ __('This product is free for you') }}.</p>
|
</div>
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.col -->
|
<!-- /.col -->
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
|
@ -110,10 +101,10 @@
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@if($discountpercent&&$discountvalue)
|
@if ($discountpercent && $discountvalue)
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ __('Discount') }} ({{ $discountpercent }}%):</th>
|
<th>{{ __('Discount') }} ({{ $discountpercent }}%):</th>
|
||||||
<td>{{$product->formatToCurrency($discountvalue)}}</td>
|
<td>{{ $product->formatToCurrency($discountvalue) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -138,42 +129,20 @@
|
||||||
<!-- this row will not appear when printing -->
|
<!-- this row will not appear when printing -->
|
||||||
<div class="row no-print">
|
<div class="row no-print">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<a type="button" :href="paymentRoute" :disabled="!paymentRoute"
|
<button :disabled="!payment_method || clicked"
|
||||||
:class="!paymentRoute ? 'disabled' : ''" class="btn btn-success float-right"><i
|
:class="!payment_method || clicked ? 'disabled' : ''"
|
||||||
class="far fa-credit-card mr-2"></i>
|
class="btn btn-success float-right"><i class="far fa-credit-card mr-2"
|
||||||
|
@click="clicked = true"></i>
|
||||||
{{ __('Submit Payment') }}
|
{{ __('Submit Payment') }}
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
<!-- /.invoice -->
|
<!-- /.invoice -->
|
||||||
</div><!-- /.col -->
|
</div><!-- /.col -->
|
||||||
</div><!-- /.row -->
|
</div><!-- /.row -->
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<!-- END CONTENT -->
|
<!-- END CONTENT -->
|
||||||
|
|
||||||
<script>
|
|
||||||
function serverApp() {
|
|
||||||
return {
|
|
||||||
//loading
|
|
||||||
paymentMethod: '',
|
|
||||||
paymentRoute: ({{ $total }} == 0)?('{{ route('payment.FreePay', $product->id) }}'):'',
|
|
||||||
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
|
@endsection
|
Loading…
Reference in a new issue