PaymentController.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Events\UserUpdateCreditsEvent;
  4. use App\Http\Controllers\Controller;
  5. use App\Models\InvoiceSettings;
  6. use App\Models\PartnerDiscount;
  7. use App\Models\Payment;
  8. use App\Models\ShopProduct;
  9. use App\Models\Settings;
  10. use App\Models\User;
  11. use App\Notifications\InvoiceNotification;
  12. use App\Notifications\ConfirmPaymentNotification;
  13. use Exception;
  14. use Illuminate\Contracts\Foundation\Application;
  15. use Illuminate\Contracts\View\Factory;
  16. use Illuminate\Contracts\View\View;
  17. use Illuminate\Http\JsonResponse;
  18. use Illuminate\Http\RedirectResponse;
  19. use Illuminate\Http\Request;
  20. use Illuminate\Support\Facades\Auth;
  21. use Illuminate\Support\Facades\DB;
  22. use Illuminate\Support\Facades\Log;
  23. use Illuminate\Support\Facades\Storage;
  24. use LaravelDaily\Invoices\Classes\Buyer;
  25. use LaravelDaily\Invoices\Classes\InvoiceItem;
  26. use LaravelDaily\Invoices\Classes\Party;
  27. use LaravelDaily\Invoices\Invoice;
  28. use PayPalCheckoutSdk\Core\PayPalHttpClient;
  29. use PayPalCheckoutSdk\Core\ProductionEnvironment;
  30. use PayPalCheckoutSdk\Core\SandboxEnvironment;
  31. use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
  32. use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
  33. use PayPalHttp\HttpException;
  34. use Stripe\Stripe;
  35. use Symfony\Component\Intl\Currencies;
  36. class PaymentController extends Controller
  37. {
  38. /**
  39. * @return Application|Factory|View
  40. */
  41. public function index()
  42. {
  43. return view('admin.payments.index')->with([
  44. 'payments' => Payment::paginate(15)
  45. ]);
  46. }
  47. /**
  48. * @param Request $request
  49. * @param ShopProduct $shopProduct
  50. * @return Application|Factory|View
  51. */
  52. public function checkOut(Request $request, ShopProduct $shopProduct)
  53. {
  54. return view('store.checkout')->with([
  55. 'product' => $shopProduct,
  56. 'discountpercent' => PartnerDiscount::getDiscount(),
  57. 'discountvalue' => PartnerDiscount::getDiscount() * $shopProduct->price/100,
  58. 'discountedprice' => $shopProduct->getPriceAfterDiscount(),
  59. 'taxvalue' => $shopProduct->getTaxValue(),
  60. 'taxpercent' => $shopProduct->getTaxPercent(),
  61. 'total' => $shopProduct->getTotalPrice()
  62. ]);
  63. }
  64. /**
  65. * @param Request $request
  66. * @param ShopProduct $shopProduct
  67. * @return RedirectResponse
  68. */
  69. public function PaypalPay(Request $request, ShopProduct $shopProduct)
  70. {
  71. $request = new OrdersCreateRequest();
  72. $request->prefer('return=representation');
  73. $request->body = [
  74. "intent" => "CAPTURE",
  75. "purchase_units" => [
  76. [
  77. "reference_id" => uniqid(),
  78. "description" => $shopProduct->display . (PartnerDiscount::getDiscount()?(" (" . __('Discount') . " " . PartnerDiscount::getDiscount() . '%)'):""),
  79. "amount" => [
  80. "value" => $shopProduct->getTotalPrice(),
  81. 'currency_code' => strtoupper($shopProduct->currency_code),
  82. 'breakdown' => [
  83. 'item_total' =>
  84. [
  85. 'currency_code' => strtoupper($shopProduct->currency_code),
  86. 'value' => $shopProduct->getPriceAfterDiscount(),
  87. ],
  88. 'tax_total' =>
  89. [
  90. 'currency_code' => strtoupper($shopProduct->currency_code),
  91. 'value' => $shopProduct->getTaxValue(),
  92. ]
  93. ]
  94. ]
  95. ]
  96. ],
  97. "application_context" => [
  98. "cancel_url" => route('payment.Cancel'),
  99. "return_url" => route('payment.PaypalSuccess', ['product' => $shopProduct->id]),
  100. 'brand_name' => config('app.name', 'Laravel'),
  101. 'shipping_preference' => 'NO_SHIPPING'
  102. ]
  103. ];
  104. try {
  105. // Call API with your client and get a response for your call
  106. $response = $this->getPayPalClient()->execute($request);
  107. return redirect()->away($response->result->links[1]->href);
  108. // If call returns body in response, you can get the deserialized version from the result attribute of the response
  109. } catch (HttpException $ex) {
  110. echo $ex->statusCode;
  111. dd(json_decode($ex->getMessage()));
  112. }
  113. }
  114. /**
  115. * @return PayPalHttpClient
  116. */
  117. protected function getPayPalClient()
  118. {
  119. $environment = env('APP_ENV') == 'local'
  120. ? new SandboxEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret())
  121. : new ProductionEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret());
  122. return new PayPalHttpClient($environment);
  123. }
  124. /**
  125. * @return string
  126. */
  127. protected function getPaypalClientId()
  128. {
  129. return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
  130. }
  131. /**
  132. * @return string
  133. */
  134. protected function getPaypalClientSecret()
  135. {
  136. return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : config("SETTINGS::PAYMENTS:PAYPAL:SECRET");
  137. }
  138. /**
  139. * @param Request $laravelRequest
  140. */
  141. public function PaypalSuccess(Request $laravelRequest)
  142. {
  143. /** @var ShopProduct $shopProduct */
  144. $shopProduct = ShopProduct::findOrFail($laravelRequest->input('product'));
  145. /** @var User $user */
  146. $user = Auth::user();
  147. $request = new OrdersCaptureRequest($laravelRequest->input('token'));
  148. $request->prefer('return=representation');
  149. try {
  150. // Call API with your client and get a response for your call
  151. $response = $this->getPayPalClient()->execute($request);
  152. if ($response->statusCode == 201 || $response->statusCode == 200) {
  153. //update server limit
  154. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  155. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  156. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  157. }
  158. }
  159. //update User with bought item
  160. if ($shopProduct->type=="Credits") {
  161. $user->increment('credits', $shopProduct->quantity);
  162. }elseif ($shopProduct->type=="Server slots"){
  163. $user->increment('server_limit', $shopProduct->quantity);
  164. }
  165. //update role give Referral-reward
  166. if ($user->role == 'member') {
  167. $user->update(['role' => 'client']);
  168. if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits"){
  169. if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
  170. $ref_user = User::findOrFail($ref_user->referral_id);
  171. $increment = number_format($shopProduct->quantity*(PartnerDiscount::getCommission($ref_user->id))/100,0,"","");
  172. $ref_user->increment('credits', $increment);
  173. //LOGS REFERRALS IN THE ACTIVITY LOG
  174. activity()
  175. ->performedOn($user)
  176. ->causedBy($ref_user)
  177. ->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  178. }
  179. }
  180. }
  181. //store payment
  182. $payment = Payment::create([
  183. 'user_id' => $user->id,
  184. 'payment_id' => $response->result->id,
  185. 'payment_method' => 'paypal',
  186. 'type' => $shopProduct->type,
  187. 'status' => 'paid',
  188. 'amount' => $shopProduct->quantity,
  189. 'price' => $shopProduct->price,
  190. 'tax_value' => $shopProduct->getTaxValue(),
  191. 'tax_percent' => $shopProduct->getTaxPercent(),
  192. 'total_price' => $shopProduct->getTotalPrice(),
  193. 'currency_code' => $shopProduct->currency_code,
  194. 'shop_item_product_id' => $shopProduct->id,
  195. ]);
  196. event(new UserUpdateCreditsEvent($user));
  197. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  198. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  199. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  200. }
  201. //redirect back to home
  202. return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
  203. }
  204. // If call returns body in response, you can get the deserialized version from the result attribute of the response
  205. if (env('APP_ENV') == 'local') {
  206. dd($response);
  207. } else {
  208. abort(500);
  209. }
  210. } catch (HttpException $ex) {
  211. if (env('APP_ENV') == 'local') {
  212. echo $ex->statusCode;
  213. dd($ex->getMessage());
  214. } else {
  215. abort(422);
  216. }
  217. }
  218. }
  219. /**
  220. * @param Request $request
  221. */
  222. public function Cancel(Request $request)
  223. {
  224. return redirect()->route('store.index')->with('success', 'Payment was Canceled');
  225. }
  226. /**
  227. * @param Request $request
  228. * @param ShopProduct $shopProduct
  229. * @return RedirectResponse
  230. */
  231. public function StripePay(Request $request, ShopProduct $shopProduct)
  232. {
  233. $stripeClient = $this->getStripeClient();
  234. $request = $stripeClient->checkout->sessions->create([
  235. 'line_items' => [
  236. [
  237. 'price_data' => [
  238. 'currency' => $shopProduct->currency_code,
  239. 'product_data' => [
  240. 'name' => $shopProduct->display . (PartnerDiscount::getDiscount()?(" (" . __('Discount') . " " . PartnerDiscount::getDiscount() . '%)'):""),
  241. 'description' => $shopProduct->description,
  242. ],
  243. 'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
  244. ],
  245. 'quantity' => 1,
  246. ],
  247. [
  248. 'price_data' => [
  249. 'currency' => $shopProduct->currency_code,
  250. 'product_data' => [
  251. 'name' => __('Tax'),
  252. 'description' => $shopProduct->getTaxPercent() . "%",
  253. ],
  254. 'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
  255. ],
  256. 'quantity' => 1,
  257. ]
  258. ],
  259. 'mode' => 'payment',
  260. "payment_method_types" => str_getcsv(config("SETTINGS::PAYMENTS:STRIPE:METHODS")),
  261. 'success_url' => route('payment.StripeSuccess', ['product' => $shopProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}',
  262. 'cancel_url' => route('payment.Cancel'),
  263. ]);
  264. return redirect($request->url, 303);
  265. }
  266. /**
  267. * @param Request $request
  268. */
  269. public function StripeSuccess(Request $request)
  270. {
  271. /** @var ShopProduct $shopProduct */
  272. $shopProduct = ShopProduct::findOrFail($request->input('product'));
  273. /** @var User $user */
  274. $user = Auth::user();
  275. $stripeClient = $this->getStripeClient();
  276. try {
  277. //get stripe data
  278. $paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
  279. $paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
  280. //get DB entry of this payment ID if existing
  281. $paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
  282. // check if payment is 100% completed and payment does not exist in db already
  283. if ($paymentSession->status == "complete" && $paymentIntent->status == "succeeded" && $paymentDbEntry == 0) {
  284. //update server limit
  285. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  286. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  287. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  288. }
  289. }
  290. //update User with bought item
  291. if ($shopProduct->type=="Credits") {
  292. $user->increment('credits', $shopProduct->quantity);
  293. }elseif ($shopProduct->type=="Server slots"){
  294. $user->increment('server_limit', $shopProduct->quantity);
  295. }
  296. //update role give Referral-reward
  297. if ($user->role == 'member') {
  298. $user->update(['role' => 'client']);
  299. if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits"){
  300. if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
  301. $ref_user = User::findOrFail($ref_user->referral_id);
  302. $increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
  303. $ref_user->increment('credits', $increment);
  304. //LOGS REFERRALS IN THE ACTIVITY LOG
  305. activity()
  306. ->performedOn($user)
  307. ->causedBy($ref_user)
  308. ->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  309. }
  310. }
  311. }
  312. //store paid payment
  313. $payment = Payment::create([
  314. 'user_id' => $user->id,
  315. 'payment_id' => $paymentSession->payment_intent,
  316. 'payment_method' => 'stripe',
  317. 'type' => $shopProduct->type,
  318. 'status' => 'paid',
  319. 'amount' => $shopProduct->quantity,
  320. 'price' => $shopProduct->price,
  321. 'tax_value' => $shopProduct->getTaxValue(),
  322. 'total_price' => $shopProduct->getTotalPrice(),
  323. 'tax_percent' => $shopProduct->getTaxPercent(),
  324. 'currency_code' => $shopProduct->currency_code,
  325. 'shop_item_product_id' => $shopProduct->id,
  326. ]);
  327. //payment notification
  328. $user->notify(new ConfirmPaymentNotification($payment));
  329. event(new UserUpdateCreditsEvent($user));
  330. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  331. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  332. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  333. }
  334. //redirect back to home
  335. return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
  336. } else {
  337. if ($paymentIntent->status == "processing") {
  338. //store processing payment
  339. $payment = Payment::create([
  340. 'user_id' => $user->id,
  341. 'payment_id' => $paymentSession->payment_intent,
  342. 'payment_method' => 'stripe',
  343. 'type' => $shopProduct->type,
  344. 'status' => 'processing',
  345. 'amount' => $shopProduct->quantity,
  346. 'price' => $shopProduct->price,
  347. 'tax_value' => $shopProduct->getTaxValue(),
  348. 'total_price' => $shopProduct->getTotalPrice(),
  349. 'tax_percent' => $shopProduct->getTaxPercent(),
  350. 'currency_code' => $shopProduct->currency_code,
  351. 'shop_item_product_id' => $shopProduct->id,
  352. ]);
  353. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  354. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  355. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  356. }
  357. //redirect back to home
  358. return redirect()->route('home')->with('success', __('Your payment is being processed!'));
  359. }
  360. if ($paymentDbEntry == 0 && $paymentIntent->status != "processing") {
  361. $stripeClient->paymentIntents->cancel($paymentIntent->id);
  362. //redirect back to home
  363. return redirect()->route('home')->with('success', __('Your payment has been canceled!'));
  364. } else {
  365. abort(402);
  366. }
  367. }
  368. } catch (HttpException $ex) {
  369. if (env('APP_ENV') == 'local') {
  370. echo $ex->statusCode;
  371. dd($ex->getMessage());
  372. } else {
  373. abort(422);
  374. }
  375. }
  376. }
  377. /**
  378. * @param Request $request
  379. */
  380. protected function handleStripePaymentSuccessHook($paymentIntent)
  381. {
  382. try {
  383. // Get payment db entry
  384. $payment = Payment::where('payment_id', $paymentIntent->id)->first();
  385. $user = User::where('id', $payment->user_id)->first();
  386. if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
  387. //update server limit
  388. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  389. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  390. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  391. }
  392. }
  393. //update User with bought item
  394. if ($shopProduct->type=="Credits") {
  395. $user->increment('credits', $shopProduct->quantity);
  396. }elseif ($shopProduct->type=="Server slots"){
  397. $user->increment('server_limit', $shopProduct->quantity);
  398. }
  399. //update role give Referral-reward
  400. if ($user->role == 'member') {
  401. $user->update(['role' => 'client']);
  402. if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both")&& $shopProduct->type=="Credits"){
  403. if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
  404. $ref_user = User::findOrFail($ref_user->referral_id);
  405. $increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
  406. $ref_user->increment('credits', $increment);
  407. //LOGS REFERRALS IN THE ACTIVITY LOG
  408. activity()
  409. ->performedOn($user)
  410. ->causedBy($ref_user)
  411. ->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  412. }
  413. }
  414. }
  415. //update payment db entry status
  416. $payment->update(['status' => 'paid']);
  417. //payment notification
  418. $user->notify(new ConfirmPaymentNotification($payment));
  419. event(new UserUpdateCreditsEvent($user));
  420. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  421. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  422. $this->createInvoice($user, $payment, 'paid', strtoupper($paymentIntent->currency));
  423. }
  424. }
  425. } catch (HttpException $ex) {
  426. abort(422);
  427. }
  428. }
  429. /**
  430. * @param Request $request
  431. */
  432. public function StripeWebhooks(Request $request)
  433. {
  434. \Stripe\Stripe::setApiKey($this->getStripeSecret());
  435. try {
  436. $payload = @file_get_contents('php://input');
  437. $sig_header = $request->header('Stripe-Signature');
  438. $event = null;
  439. $event = \Stripe\Webhook::constructEvent(
  440. $payload,
  441. $sig_header,
  442. $this->getStripeEndpointSecret()
  443. );
  444. } catch (\UnexpectedValueException $e) {
  445. // Invalid payload
  446. abort(400);
  447. } catch (\Stripe\Exception\SignatureVerificationException $e) {
  448. // Invalid signature
  449. abort(400);
  450. }
  451. // Handle the event
  452. switch ($event->type) {
  453. case 'payment_intent.succeeded':
  454. $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
  455. $this->handleStripePaymentSuccessHook($paymentIntent);
  456. break;
  457. default:
  458. echo 'Received unknown event type ' . $event->type;
  459. }
  460. }
  461. /**
  462. * @return \Stripe\StripeClient
  463. */
  464. protected function getStripeClient()
  465. {
  466. return new \Stripe\StripeClient($this->getStripeSecret());
  467. }
  468. /**
  469. * @return string
  470. */
  471. protected function getStripeSecret()
  472. {
  473. return env('APP_ENV') == 'local'
  474. ? config("SETTINGS::PAYMENTS:STRIPE:TEST_SECRET")
  475. : config("SETTINGS::PAYMENTS:STRIPE:SECRET");
  476. }
  477. /**
  478. * @return string
  479. */
  480. protected function getStripeEndpointSecret()
  481. {
  482. return env('APP_ENV') == 'local'
  483. ? config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET")
  484. : config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET");
  485. }
  486. protected function createInvoice($user, $payment, $paymentStatus, $currencyCode)
  487. {
  488. $shopProduct = ShopProduct::where('id', $payment->shop_item_product_id)->first();
  489. //create invoice
  490. $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
  491. $newInvoiceID = $lastInvoiceID + 1;
  492. $logoPath = storage_path('app/public/logo.png');
  493. $seller = new Party([
  494. 'name' => config("SETTINGS::INVOICE:COMPANY_NAME"),
  495. 'phone' => config("SETTINGS::INVOICE:COMPANY_PHONE"),
  496. 'address' => config("SETTINGS::INVOICE:COMPANY_ADDRESS"),
  497. 'vat' => config("SETTINGS::INVOICE:COMPANY_VAT"),
  498. 'custom_fields' => [
  499. 'E-Mail' => config("SETTINGS::INVOICE:COMPANY_MAIL"),
  500. "Web" => config("SETTINGS::INVOICE:COMPANY_WEBSITE")
  501. ],
  502. ]);
  503. $customer = new Buyer([
  504. 'name' => $user->name,
  505. 'custom_fields' => [
  506. 'E-Mail' => $user->email,
  507. 'Client ID' => $user->id,
  508. ],
  509. ]);
  510. $item = (new InvoiceItem())
  511. ->title($shopProduct->description)
  512. ->pricePerUnit($shopProduct->price);
  513. $notes = [
  514. __("Payment method") . ": " . $payment->payment_method,
  515. ];
  516. $notes = implode("<br>", $notes);
  517. $invoice = Invoice::make()
  518. ->template('controlpanel')
  519. ->name(__("Invoice"))
  520. ->buyer($customer)
  521. ->seller($seller)
  522. ->discountByPercent(PartnerDiscount::getDiscount())
  523. ->taxRate(floatval($shopProduct->getTaxPercent()))
  524. ->shipping(0)
  525. ->addItem($item)
  526. ->status(__($paymentStatus))
  527. ->series(now()->format('mY'))
  528. ->delimiter("-")
  529. ->sequence($newInvoiceID)
  530. ->serialNumberFormat(config("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
  531. ->currencyCode($currencyCode)
  532. ->currencySymbol(Currencies::getSymbol($currencyCode))
  533. ->notes($notes);
  534. if (file_exists($logoPath)) {
  535. $invoice->logo($logoPath);
  536. }
  537. //Save the invoice in "storage\app\invoice\USER_ID\YEAR"
  538. $invoice->filename = $invoice->getSerialNumber() . '.pdf';
  539. $invoice->render();
  540. Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
  541. \App\Models\Invoice::create([
  542. 'invoice_user' => $user->id,
  543. 'invoice_name' => $invoice->getSerialNumber(),
  544. 'payment_id' => $payment->payment_id,
  545. ]);
  546. //Send Invoice per Mail
  547. $user->notify(new InvoiceNotification($invoice, $user, $payment));
  548. }
  549. /**
  550. * @return JsonResponse|mixed
  551. * @throws Exception
  552. */
  553. public function dataTable()
  554. {
  555. $query = Payment::with('user');
  556. return datatables($query)
  557. ->editColumn('user', function (Payment $payment) {
  558. return
  559. ($payment->user)?'<a href="'.route('admin.users.show', $payment->user->id).'">'.$payment->user->name.'</a>':__('Unknown user');
  560. })
  561. ->editColumn('price', function (Payment $payment) {
  562. return $payment->formatToCurrency($payment->price);
  563. })
  564. ->editColumn('tax_value', function (Payment $payment) {
  565. return $payment->formatToCurrency($payment->tax_value);
  566. })
  567. ->editColumn('tax_percent', function (Payment $payment) {
  568. return $payment->tax_percent . ' %';
  569. })
  570. ->editColumn('total_price', function (Payment $payment) {
  571. return $payment->formatToCurrency($payment->total_price);
  572. })
  573. ->editColumn('created_at', function (Payment $payment) {
  574. return $payment->created_at ? $payment->created_at->diffForHumans() : '';
  575. })
  576. ->addColumn('actions', function (Payment $payment) {
  577. 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>';
  578. })
  579. ->rawColumns(['actions', 'user'])
  580. ->make(true);
  581. }
  582. }