with([ 'payments' => Payment::paginate(15) ]); } /** * @param Request $request * @param CreditProduct $creditProduct * @return Application|Factory|View */ public function checkOut(Request $request, CreditProduct $creditProduct) { return view('store.checkout')->with([ 'product' => $creditProduct, 'taxvalue' => $creditProduct->getTaxValue(), 'taxpercent' => $creditProduct->getTaxPercent(), 'total' => $creditProduct->getTotalPrice() ]); } /** * @param Request $request * @param CreditProduct $creditProduct * @return RedirectResponse */ public function PaypalPay(Request $request, CreditProduct $creditProduct) { $request = new OrdersCreateRequest(); $request->prefer('return=representation'); $request->body = [ "intent" => "CAPTURE", "purchase_units" => [ [ "reference_id" => uniqid(), "description" => $creditProduct->description, "amount" => [ "value" => $creditProduct->getTotalPrice(), 'currency_code' => strtoupper($creditProduct->currency_code), 'breakdown' => [ 'item_total' => [ 'currency_code' => strtoupper($creditProduct->currency_code), 'value' => $creditProduct->price, ], 'tax_total' => [ 'currency_code' => strtoupper($creditProduct->currency_code), 'value' => $creditProduct->getTaxValue(), ] ] ] ] ], "application_context" => [ "cancel_url" => route('payment.Cancel'), "return_url" => route('payment.PaypalSuccess', ['product' => $creditProduct->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 = $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' ? env('PAYPAL_SANDBOX_CLIENT_ID') : env('PAYPAL_CLIENT_ID'); } /** * @return string */ protected function getPaypalClientSecret() { return env('APP_ENV') == 'local' ? env('PAYPAL_SANDBOX_SECRET') : env('PAYPAL_SECRET'); } /** * @param Request $laravelRequest */ public function PaypalSuccess(Request $laravelRequest) { /** @var CreditProduct $creditProduct */ $creditProduct = CreditProduct::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 credits $user->increment('credits', $creditProduct->quantity); //update server limit if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) { if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) { $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]); } } //update role if ($user->role == 'member') { $user->update(['role' => 'client']); } //store payment $payment = Payment::create([ 'user_id' => $user->id, 'payment_id' => $response->result->id, 'payment_method' => 'paypal', 'type' => 'Credits', 'status' => 'paid', 'amount' => $creditProduct->quantity, 'price' => $creditProduct->price, 'tax_value' => $creditProduct->getTaxValue(), 'tax_percent' => $creditProduct->getTaxPercent(), 'total_price' => $creditProduct->getTotalPrice(), 'currency_code' => $creditProduct->currency_code, 'credit_product_id' => $creditProduct->id, ]); event(new UserUpdateCreditsEvent($user)); $this->createInvoice($user, $payment, 'paid'); //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); } } } /** * @param Request $request */ public function Cancel(Request $request) { return redirect()->route('store.index')->with('success', 'Payment was Canceled'); } /** * @param Request $request * @param CreditProduct $creditProduct * @return RedirectResponse */ public function StripePay(Request $request, CreditProduct $creditProduct) { $stripeClient = $this->getStripeClient(); $request = $stripeClient->checkout->sessions->create([ 'line_items' => [ [ 'price_data' => [ 'currency' => $creditProduct->currency_code, 'product_data' => [ 'name' => $creditProduct->display, 'description' => $creditProduct->description, ], 'unit_amount_decimal' => round($creditProduct->price * 100, 2), ], 'quantity' => 1, ], [ 'price_data' => [ 'currency' => $creditProduct->currency_code, 'product_data' => [ 'name' => 'Product Tax', 'description' => $creditProduct->getTaxPercent() . "%", ], 'unit_amount_decimal' => round($creditProduct->getTaxValue(), 2) * 100, ], 'quantity' => 1, ] ], 'mode' => 'payment', "payment_method_types" => str_getcsv(env('STRIPE_METHODS')), 'success_url' => route('payment.StripeSuccess', ['product' => $creditProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => route('payment.Cancel'), ]); return redirect($request->url, 303); } /** * @param Request $request */ public function StripeSuccess(Request $request) { /** @var CreditProduct $creditProduct */ $creditProduct = CreditProduct::findOrFail($request->input('product')); /** @var User $user */ $user = Auth::user(); $stripeClient = $this->getStripeClient(); try { //get stripe data $paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id')); $paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent); //get DB entry of this payment ID if existing $paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count(); // check if payment is 100% completed and payment does not exist in db already if ($paymentSession->status == "complete" && $paymentIntent->status == "succeeded" && $paymentDbEntry == 0) { //update credits $user->increment('credits', $creditProduct->quantity); //update server limit if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) { if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) { $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]); } } //update role if ($user->role == 'member') { $user->update(['role' => 'client']); } //store paid payment $payment = Payment::create([ 'user_id' => $user->id, 'payment_id' => $paymentSession->payment_intent, 'payment_method' => 'stripe', 'type' => 'Credits', 'status' => 'paid', 'amount' => $creditProduct->quantity, 'price' => $creditProduct->price, 'tax_value' => $creditProduct->getTaxValue(), 'total_price' => $creditProduct->getTotalPrice(), 'tax_percent' => $creditProduct->getTaxPercent(), 'currency_code' => $creditProduct->currency_code, 'credit_product_id' => $creditProduct->id, ]); //payment notification $user->notify(new ConfirmPaymentNotification($payment)); event(new UserUpdateCreditsEvent($user)); $this->createInvoice($user, $payment, 'paid'); //redirect back to home return redirect()->route('home')->with('success', __('Your credit balance has been increased!')); } else { if ($paymentIntent->status == "processing") { //store processing payment $payment = Payment::create([ 'user_id' => $user->id, 'payment_id' => $paymentSession->payment_intent, 'payment_method' => 'stripe', 'type' => 'Credits', 'status' => 'processing', 'amount' => $creditProduct->quantity, 'price' => $creditProduct->price, 'tax_value' => $creditProduct->getTaxValue(), 'total_price' => $creditProduct->getTotalPrice(), 'tax_percent' => $creditProduct->getTaxPercent(), 'currency_code' => $creditProduct->currency_code, 'credit_product_id' => $creditProduct->id, ]); $this->createInvoice($user, $payment, 'processing'); //redirect back to home return redirect()->route('home')->with('success', __('Your payment is being processed!')); } if ($paymentDbEntry == 0 && $paymentIntent->status != "processing") { $stripeClient->paymentIntents->cancel($paymentIntent->id); //redirect back to home return redirect()->route('home')->with('success', __('Your payment has been canceled!')); } else { abort(402); } } } catch (HttpException $ex) { if (env('APP_ENV') == 'local') { echo $ex->statusCode; dd($ex->getMessage()); } else { abort(422); } } } /** * @param Request $request */ protected function handleStripePaymentSuccessHook($paymentIntent) { try { // Get payment db entry $payment = Payment::where('payment_id', $paymentIntent->id)->first(); $user = User::where('id', $payment->user_id)->first(); if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') { // Increment User Credits $user->increment('credits', $payment->amount); //update server limit if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) { if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) { $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]); } } //update role if ($user->role == 'member') { $user->update(['role' => 'client']); } //update payment db entry status $payment->update(['status' => 'paid']); //payment notification $user->notify(new ConfirmPaymentNotification($payment)); event(new UserUpdateCreditsEvent($user)); $this->createInvoice($user, $payment, 'paid'); } } catch (HttpException $ex) { abort(422); } } /** * @param Request $request */ public function StripeWebhooks(Request $request) { \Stripe\Stripe::setApiKey($this->getStripeSecret()); try { $payload = @file_get_contents('php://input'); $sig_header = $request->header('Stripe-Signature'); $event = null; $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $this->getStripeEndpointSecret() ); } catch (\UnexpectedValueException $e) { // Invalid payload abort(400); } catch (\Stripe\Exception\SignatureVerificationException $e) { // Invalid signature abort(400); } // Handle the event switch ($event->type) { case 'payment_intent.succeeded': $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent $this->handleStripePaymentSuccessHook($paymentIntent); break; default: echo 'Received unknown event type ' . $event->type; } } /** * @return \Stripe\StripeClient */ protected function getStripeClient() { return new \Stripe\StripeClient($this->getStripeSecret()); } /** * @return string */ protected function getStripeSecret() { return env('APP_ENV') == 'local' ? env('STRIPE_TEST_SECRET') : env('STRIPE_SECRET'); } /** * @return string */ protected function getStripeEndpointSecret() { return env('APP_ENV') == 'local' ? env('STRIPE_ENDPOINT_TEST_SECRET') : env('STRIPE_ENDPOINT_SECRET'); } protected function createInvoice($user, $payment, $paymentStatus) { $creditProduct = CreditProduct::where('id', $payment->credit_product_id)->first(); //create invoice $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id"); $newInvoiceID = $lastInvoiceID + 1; $InvoiceSettings = InvoiceSettings::query()->first(); $logoPath = storage_path('app/public/logo.png'); $seller = new Party([ 'name' => $InvoiceSettings->company_name, 'phone' => $InvoiceSettings->company_phone, 'address' => $InvoiceSettings->company_adress, 'vat' => $InvoiceSettings->company_vat, 'custom_fields' => [ 'E-Mail' => $InvoiceSettings->company_mail, "Web" => $InvoiceSettings->company_web ], ]); $customer = new Buyer([ 'name' => $user->name, 'custom_fields' => [ 'E-Mail' => $user->email, 'Client ID' => $user->id, ], ]); $item = (new InvoiceItem()) ->title($creditProduct->description) ->pricePerUnit($creditProduct->price); $invoice = Invoice::make() ->template('controlpanel') ->name(__("Invoice")) ->buyer($customer) ->seller($seller) ->discountByPercent(0) ->taxRate(floatval($creditProduct->getTaxPercent())) ->shipping(0) ->addItem($item) ->status(__($paymentStatus)) ->series(now()->format('mY')) ->delimiter("-") ->sequence($newInvoiceID) ->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}'); if (file_exists($logoPath)) { $invoice->logo($logoPath); } //Save the invoice in "storage\app\invoice\USER_ID\YEAR" $invoice->filename = $invoice->getSerialNumber() . '.pdf'; $invoice->render(); Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output); \App\Models\Invoice::create([ 'invoice_user' => $user->id, 'invoice_name' => $invoice->getSerialNumber(), 'payment_id' => $payment->payment_id, ]); //Send Invoice per Mail $user->notify(new InvoiceNotification($invoice, $user, $payment)); } /** * @return JsonResponse|mixed * @throws Exception */ public function dataTable() { $query = Payment::with('user'); return datatables($query) ->editColumn('user', function (Payment $payment) { return $payment->user->name; }) ->editColumn('price', function (Payment $payment) { return $payment->formatToCurrency($payment->price); }) ->editColumn('tax_value', function (Payment $payment) { return $payment->formatToCurrency($payment->tax_value); }) ->editColumn('tax_percent', function (Payment $payment) { return $payment->tax_percent . ' %'; }) ->editColumn('total_price', function (Payment $payment) { return $payment->formatToCurrency($payment->total_price); }) ->editColumn('created_at', function (Payment $payment) { return $payment->created_at ? $payment->created_at->diffForHumans() : ''; }) ->make(); } }