PaymentController.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Events\UserUpdateCreditsEvent;
  4. use App\Http\Controllers\Controller;
  5. use App\Models\PartnerDiscount;
  6. use App\Models\Payment;
  7. use App\Models\Settings;
  8. use App\Models\ShopProduct;
  9. use App\Models\User;
  10. use App\Notifications\ConfirmPaymentNotification;
  11. use App\Notifications\InvoiceNotification;
  12. use Exception;
  13. use Illuminate\Contracts\Foundation\Application;
  14. use Illuminate\Contracts\View\Factory;
  15. use Illuminate\Contracts\View\View;
  16. use Illuminate\Http\JsonResponse;
  17. use Illuminate\Http\RedirectResponse;
  18. use Illuminate\Http\Request;
  19. use Illuminate\Support\Facades\Auth;
  20. use Illuminate\Support\Facades\DB;
  21. use Illuminate\Support\Facades\Log;
  22. use Illuminate\Support\Facades\Storage;
  23. use LaravelDaily\Invoices\Classes\Buyer;
  24. use LaravelDaily\Invoices\Classes\InvoiceItem;
  25. use LaravelDaily\Invoices\Classes\Party;
  26. use LaravelDaily\Invoices\Invoice;
  27. use PayPalCheckoutSdk\Core\PayPalHttpClient;
  28. use PayPalCheckoutSdk\Core\ProductionEnvironment;
  29. use PayPalCheckoutSdk\Core\SandboxEnvironment;
  30. use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
  31. use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
  32. use PayPalHttp\HttpException;
  33. use Stripe\Stripe;
  34. use Symfony\Component\Intl\Currencies;
  35. use App\Helpers\ExtensionHelper;
  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. // get all payment gateway extensions
  55. $extensions = glob(app_path() . '/Extensions/PaymentGateways/*', GLOB_ONLYDIR);
  56. // 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
  57. $paymentGateways = [];
  58. foreach ($extensions as $extension) {
  59. $extensionName = basename($extension);
  60. $config = ExtensionHelper::getExtensionConfig($extensionName, 'PaymentGateways');
  61. if ($config) {
  62. $payment = new \stdClass();
  63. $payment->name = $config['name'];
  64. $payment->image = asset('images/Extensions/PaymentGateways/' . strtolower($extensionName) . '_logo.png');
  65. $paymentGateways[] = $payment;
  66. }
  67. }
  68. return view('store.checkout')->with([
  69. 'product' => $shopProduct,
  70. 'discountpercent' => PartnerDiscount::getDiscount(),
  71. 'discountvalue' => PartnerDiscount::getDiscount() * $shopProduct->price / 100,
  72. 'discountedprice' => $shopProduct->getPriceAfterDiscount(),
  73. 'taxvalue' => $shopProduct->getTaxValue(),
  74. 'taxpercent' => $shopProduct->getTaxPercent(),
  75. 'total' => $shopProduct->getTotalPrice(),
  76. 'paymentGateways' => $paymentGateways,
  77. ]);
  78. }
  79. /**
  80. * @param Request $request
  81. * @param ShopProduct $shopProduct
  82. * @return RedirectResponse
  83. */
  84. public function FreePay(Request $request, ShopProduct $shopProduct)
  85. {
  86. //dd($shopProduct);
  87. //check if the product is really free or the discount is 100%
  88. if($shopProduct->getTotalPrice()>0) return redirect()->route('home')->with('error', __('An error ocured. Please try again.'));
  89. //give product
  90. /** @var User $user */
  91. $user = Auth::user();
  92. //not updating server limit
  93. //update User with bought item
  94. if ($shopProduct->type=="Credits") {
  95. $user->increment('credits', $shopProduct->quantity);
  96. }elseif ($shopProduct->type=="Server slots"){
  97. $user->increment('server_limit', $shopProduct->quantity);
  98. }
  99. //skipped the referral commission, because the user did not pay anything.
  100. //not giving client role
  101. //store payment
  102. $payment = Payment::create([
  103. 'user_id' => $user->id,
  104. 'payment_id' => uniqid(),
  105. 'payment_method' => 'free',
  106. 'type' => $shopProduct->type,
  107. 'status' => 'paid',
  108. 'amount' => $shopProduct->quantity,
  109. 'price' => $shopProduct->price - ($shopProduct->price*PartnerDiscount::getDiscount()/100),
  110. 'tax_value' => $shopProduct->getTaxValue(),
  111. 'tax_percent' => $shopProduct->getTaxPercent(),
  112. 'total_price' => $shopProduct->getTotalPrice(),
  113. 'currency_code' => $shopProduct->currency_code,
  114. 'shop_item_product_id' => $shopProduct->id,
  115. ]);
  116. event(new UserUpdateCreditsEvent($user));
  117. //not sending an invoice
  118. //redirect back to home
  119. return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
  120. }
  121. /**
  122. * @param Request $request
  123. * @param ShopProduct $shopProduct
  124. * @return RedirectResponse
  125. */
  126. public function PaypalPay(Request $request, ShopProduct $shopProduct)
  127. {
  128. 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.'));
  129. $request = new OrdersCreateRequest();
  130. $request->prefer('return=representation');
  131. $request->body = [
  132. 'intent' => 'CAPTURE',
  133. 'purchase_units' => [
  134. [
  135. 'reference_id' => uniqid(),
  136. 'description' => $shopProduct->display.(PartnerDiscount::getDiscount() ? (' ('.__('Discount').' '.PartnerDiscount::getDiscount().'%)') : ''),
  137. 'amount' => [
  138. 'value' => $shopProduct->getTotalPrice(),
  139. 'currency_code' => strtoupper($shopProduct->currency_code),
  140. 'breakdown' => [
  141. 'item_total' => [
  142. 'currency_code' => strtoupper($shopProduct->currency_code),
  143. 'value' => $shopProduct->getPriceAfterDiscount(),
  144. ],
  145. 'tax_total' => [
  146. 'currency_code' => strtoupper($shopProduct->currency_code),
  147. 'value' => $shopProduct->getTaxValue(),
  148. ],
  149. ],
  150. ],
  151. ],
  152. ],
  153. 'application_context' => [
  154. 'cancel_url' => route('payment.Cancel'),
  155. 'return_url' => route('payment.PaypalSuccess', ['product' => $shopProduct->id]),
  156. 'brand_name' => config('app.name', 'Laravel'),
  157. 'shipping_preference' => 'NO_SHIPPING',
  158. ],
  159. ];
  160. try {
  161. // Call API with your client and get a response for your call
  162. $response = $this->getPayPalClient()->execute($request);
  163. return redirect()->away($response->result->links[1]->href);
  164. // If call returns body in response, you can get the deserialized version from the result attribute of the response
  165. } catch (HttpException $ex) {
  166. echo $ex->statusCode;
  167. dd(json_decode($ex->getMessage()));
  168. }
  169. }
  170. /**
  171. * @return PayPalHttpClient
  172. */
  173. protected function getPayPalClient()
  174. {
  175. $environment = env('APP_ENV') == 'local'
  176. ? new SandboxEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret())
  177. : new ProductionEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret());
  178. return new PayPalHttpClient($environment);
  179. }
  180. /**
  181. * @return string
  182. */
  183. protected function getPaypalClientId()
  184. {
  185. return env('APP_ENV') == 'local' ? config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') : config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID');
  186. }
  187. /**
  188. * @return string
  189. */
  190. protected function getPaypalClientSecret()
  191. {
  192. return env('APP_ENV') == 'local' ? config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') : config('SETTINGS::PAYMENTS:PAYPAL:SECRET');
  193. }
  194. public function pay(Request $request)
  195. {
  196. $product = ShopProduct::find($request->product_id);
  197. $paymentGateway = $request->payment_method;
  198. return redirect()->route('payment.' . $paymentGateway . 'Pay', ['shopProduct' => $product->id]);
  199. }
  200. /**
  201. */
  202. public function PaypalSuccess(Request $laravelRequest)
  203. {
  204. $request = new OrdersCaptureRequest($laravelRequest->input('token'));
  205. $request->prefer('return=representation');
  206. try {
  207. // Call API with your client and get a response for your call
  208. $response = $this->getPayPalClient()->execute($request);
  209. if ($response->statusCode == 201 || $response->statusCode == 200) {
  210. //update server limit
  211. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  212. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  213. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  214. }
  215. }
  216. //update User with bought item
  217. if ($shopProduct->type == 'Credits') {
  218. $user->increment('credits', $shopProduct->quantity);
  219. } elseif ($shopProduct->type == 'Server slots') {
  220. $user->increment('server_limit', $shopProduct->quantity);
  221. }
  222. //give referral commission always
  223. if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits' && config('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') == 'true') {
  224. if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
  225. $ref_user = User::findOrFail($ref_user->referral_id);
  226. $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, '', '');
  227. $ref_user->increment('credits', $increment);
  228. //LOGS REFERRALS IN THE ACTIVITY LOG
  229. activity()
  230. ->performedOn($user)
  231. ->causedBy($ref_user)
  232. ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  233. }
  234. }
  235. //update role give Referral-reward
  236. if ($user->role == 'member') {
  237. $user->update(['role' => 'client']);
  238. //give referral commission only on first purchase
  239. if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits' && config('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') == 'false') {
  240. if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
  241. $ref_user = User::findOrFail($ref_user->referral_id);
  242. $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, '', '');
  243. $ref_user->increment('credits', $increment);
  244. //LOGS REFERRALS IN THE ACTIVITY LOG
  245. activity()
  246. ->performedOn($user)
  247. ->causedBy($ref_user)
  248. ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  249. }
  250. }
  251. }
  252. //store payment
  253. $payment = Payment::create([
  254. 'user_id' => $user->id,
  255. 'payment_id' => $response->result->id,
  256. 'payment_method' => 'paypal',
  257. 'type' => $shopProduct->type,
  258. 'status' => 'paid',
  259. 'amount' => $shopProduct->quantity,
  260. 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
  261. 'tax_value' => $shopProduct->getTaxValue(),
  262. 'tax_percent' => $shopProduct->getTaxPercent(),
  263. 'total_price' => $shopProduct->getTotalPrice(),
  264. 'currency_code' => $shopProduct->currency_code,
  265. 'shop_item_product_id' => $shopProduct->id,
  266. ]);
  267. event(new UserUpdateCreditsEvent($user));
  268. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  269. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  270. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  271. }
  272. //redirect back to home
  273. return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
  274. }
  275. // If call returns body in response, you can get the deserialized version from the result attribute of the response
  276. if (env('APP_ENV') == 'local') {
  277. dd($response);
  278. } else {
  279. abort(500);
  280. }
  281. } catch (HttpException $ex) {
  282. if (env('APP_ENV') == 'local') {
  283. echo $ex->statusCode;
  284. dd($ex->getMessage());
  285. } else {
  286. abort(422);
  287. }
  288. }
  289. }
  290. /**
  291. * @param Request $request
  292. */
  293. public function Cancel(Request $request)
  294. {
  295. return redirect()->route('store.index')->with('success', 'Payment was Canceled');
  296. }
  297. /**
  298. * @param Request $request
  299. * @param ShopProduct $shopProduct
  300. * @return RedirectResponse
  301. */
  302. public function StripePay(Request $request, ShopProduct $shopProduct)
  303. {
  304. 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.'));
  305. $stripeClient = $this->getStripeClient();
  306. $request = $stripeClient->checkout->sessions->create([
  307. 'line_items' => [
  308. [
  309. 'price_data' => [
  310. 'currency' => $shopProduct->currency_code,
  311. 'product_data' => [
  312. 'name' => $shopProduct->display.(PartnerDiscount::getDiscount() ? (' ('.__('Discount').' '.PartnerDiscount::getDiscount().'%)') : ''),
  313. 'description' => $shopProduct->description,
  314. ],
  315. 'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
  316. ],
  317. 'quantity' => 1,
  318. ],
  319. [
  320. 'price_data' => [
  321. 'currency' => $shopProduct->currency_code,
  322. 'product_data' => [
  323. 'name' => __('Tax'),
  324. 'description' => $shopProduct->getTaxPercent().'%',
  325. ],
  326. 'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
  327. ],
  328. 'quantity' => 1,
  329. ],
  330. ],
  331. 'mode' => 'payment',
  332. 'payment_method_types' => str_getcsv(config('SETTINGS::PAYMENTS:STRIPE:METHODS')),
  333. 'success_url' => route('payment.StripeSuccess', ['product' => $shopProduct->id]).'&session_id={CHECKOUT_SESSION_ID}',
  334. 'cancel_url' => route('payment.Cancel'),
  335. ]);
  336. return redirect($request->url, 303);
  337. }
  338. /**
  339. * @param Request $request
  340. */
  341. public function StripeSuccess(Request $request)
  342. {
  343. /** @var ShopProduct $shopProduct */
  344. $shopProduct = ShopProduct::findOrFail($request->input('product'));
  345. /** @var User $user */
  346. $user = Auth::user();
  347. $stripeClient = $this->getStripeClient();
  348. try {
  349. //get stripe data
  350. $paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
  351. $paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
  352. //get DB entry of this payment ID if existing
  353. $paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
  354. // check if payment is 100% completed and payment does not exist in db already
  355. if ($paymentSession->status == 'complete' && $paymentIntent->status == 'succeeded' && $paymentDbEntry == 0) {
  356. //update server limit
  357. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  358. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  359. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  360. }
  361. }
  362. //update User with bought item
  363. if ($shopProduct->type == 'Credits') {
  364. $user->increment('credits', $shopProduct->quantity);
  365. } elseif ($shopProduct->type == 'Server slots') {
  366. $user->increment('server_limit', $shopProduct->quantity);
  367. }
  368. //update role give Referral-reward
  369. if ($user->role == 'member') {
  370. $user->update(['role' => 'client']);
  371. if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits') {
  372. if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
  373. $ref_user = User::findOrFail($ref_user->referral_id);
  374. $increment = number_format($shopProduct->quantity / 100 * config('SETTINGS::REFERRAL:PERCENTAGE'), 0, '', '');
  375. $ref_user->increment('credits', $increment);
  376. //LOGS REFERRALS IN THE ACTIVITY LOG
  377. activity()
  378. ->performedOn($user)
  379. ->causedBy($ref_user)
  380. ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  381. }
  382. }
  383. }
  384. //store paid payment
  385. $payment = Payment::create([
  386. 'user_id' => $user->id,
  387. 'payment_id' => $paymentSession->payment_intent,
  388. 'payment_method' => 'stripe',
  389. 'type' => $shopProduct->type,
  390. 'status' => 'paid',
  391. 'amount' => $shopProduct->quantity,
  392. 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
  393. 'tax_value' => $shopProduct->getTaxValue(),
  394. 'total_price' => $shopProduct->getTotalPrice(),
  395. 'tax_percent' => $shopProduct->getTaxPercent(),
  396. 'currency_code' => $shopProduct->currency_code,
  397. 'shop_item_product_id' => $shopProduct->id,
  398. ]);
  399. //payment notification
  400. $user->notify(new ConfirmPaymentNotification($payment));
  401. event(new UserUpdateCreditsEvent($user));
  402. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  403. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  404. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  405. }
  406. //redirect back to home
  407. return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
  408. } else {
  409. if ($paymentIntent->status == 'processing') {
  410. //store processing payment
  411. $payment = Payment::create([
  412. 'user_id' => $user->id,
  413. 'payment_id' => $paymentSession->payment_intent,
  414. 'payment_method' => 'stripe',
  415. 'type' => $shopProduct->type,
  416. 'status' => 'processing',
  417. 'amount' => $shopProduct->quantity,
  418. 'price' => $shopProduct->price,
  419. 'tax_value' => $shopProduct->getTaxValue(),
  420. 'total_price' => $shopProduct->getTotalPrice(),
  421. 'tax_percent' => $shopProduct->getTaxPercent(),
  422. 'currency_code' => $shopProduct->currency_code,
  423. 'shop_item_product_id' => $shopProduct->id,
  424. ]);
  425. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  426. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  427. $this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
  428. }
  429. //redirect back to home
  430. return redirect()->route('home')->with('success', __('Your payment is being processed!'));
  431. }
  432. if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') {
  433. $stripeClient->paymentIntents->cancel($paymentIntent->id);
  434. //redirect back to home
  435. return redirect()->route('home')->with('success', __('Your payment has been canceled!'));
  436. } else {
  437. abort(402);
  438. }
  439. }
  440. } catch (HttpException $ex) {
  441. if (env('APP_ENV') == 'local') {
  442. echo $ex->statusCode;
  443. dd($ex->getMessage());
  444. } else {
  445. abort(422);
  446. }
  447. }
  448. }
  449. /**
  450. * @param Request $request
  451. */
  452. protected function handleStripePaymentSuccessHook($paymentIntent)
  453. {
  454. try {
  455. // Get payment db entry
  456. $payment = Payment::where('payment_id', $paymentIntent->id)->first();
  457. $user = User::where('id', $payment->user_id)->first();
  458. if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
  459. //update server limit
  460. if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
  461. if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
  462. $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
  463. }
  464. }
  465. //update User with bought item
  466. if ($shopProduct->type == 'Credits') {
  467. $user->increment('credits', $shopProduct->quantity);
  468. } elseif ($shopProduct->type == 'Server slots') {
  469. $user->increment('server_limit', $shopProduct->quantity);
  470. }
  471. //update role give Referral-reward
  472. if ($user->role == 'member') {
  473. $user->update(['role' => 'client']);
  474. if ((config('SETTINGS::REFERRAL:MODE') == 'commission' || config('SETTINGS::REFERRAL:MODE') == 'both') && $shopProduct->type == 'Credits') {
  475. if ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user->id)->first()) {
  476. $ref_user = User::findOrFail($ref_user->referral_id);
  477. $increment = number_format($shopProduct->quantity / 100 * config('SETTINGS::REFERRAL:PERCENTAGE'), 0, '', '');
  478. $ref_user->increment('credits', $increment);
  479. //LOGS REFERRALS IN THE ACTIVITY LOG
  480. activity()
  481. ->performedOn($user)
  482. ->causedBy($ref_user)
  483. ->log('gained '.$increment.' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
  484. }
  485. }
  486. }
  487. //update payment db entry status
  488. $payment->update(['status' => 'paid']);
  489. //payment notification
  490. $user->notify(new ConfirmPaymentNotification($payment));
  491. event(new UserUpdateCreditsEvent($user));
  492. //only create invoice if SETTINGS::INVOICE:ENABLED is true
  493. if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
  494. $this->createInvoice($user, $payment, 'paid', strtoupper($paymentIntent->currency));
  495. }
  496. }
  497. } catch (HttpException $ex) {
  498. abort(422);
  499. }
  500. }
  501. /**
  502. * @param Request $request
  503. */
  504. public function StripeWebhooks(Request $request)
  505. {
  506. \Stripe\Stripe::setApiKey($this->getStripeSecret());
  507. try {
  508. $payload = @file_get_contents('php://input');
  509. $sig_header = $request->header('Stripe-Signature');
  510. $event = null;
  511. $event = \Stripe\Webhook::constructEvent(
  512. $payload,
  513. $sig_header,
  514. $this->getStripeEndpointSecret()
  515. );
  516. } catch (\UnexpectedValueException $e) {
  517. // Invalid payload
  518. abort(400);
  519. } catch (\Stripe\Exception\SignatureVerificationException $e) {
  520. // Invalid signature
  521. abort(400);
  522. }
  523. // Handle the event
  524. switch ($event->type) {
  525. case 'payment_intent.succeeded':
  526. $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
  527. $this->handleStripePaymentSuccessHook($paymentIntent);
  528. break;
  529. default:
  530. echo 'Received unknown event type '.$event->type;
  531. }
  532. }
  533. /**
  534. * @return \Stripe\StripeClient
  535. */
  536. protected function getStripeClient()
  537. {
  538. return new \Stripe\StripeClient($this->getStripeSecret());
  539. }
  540. /**
  541. * @return string
  542. */
  543. protected function getStripeSecret()
  544. {
  545. return env('APP_ENV') == 'local'
  546. ? config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET')
  547. : config('SETTINGS::PAYMENTS:STRIPE:SECRET');
  548. }
  549. /**
  550. * @return string
  551. */
  552. protected function getStripeEndpointSecret()
  553. {
  554. return env('APP_ENV') == 'local'
  555. ? config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET')
  556. : config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET');
  557. }
  558. protected function createInvoice($user, $payment, $paymentStatus, $currencyCode)
  559. {
  560. $shopProduct = ShopProduct::where('id', $payment->shop_item_product_id)->first();
  561. //create invoice
  562. $lastInvoiceID = \App\Models\Invoice::where('invoice_name', 'like', '%'.now()->format('mY').'%')->count('id');
  563. $newInvoiceID = $lastInvoiceID + 1;
  564. $logoPath = storage_path('app/public/logo.png');
  565. $seller = new Party([
  566. 'name' => config('SETTINGS::INVOICE:COMPANY_NAME'),
  567. 'phone' => config('SETTINGS::INVOICE:COMPANY_PHONE'),
  568. 'address' => config('SETTINGS::INVOICE:COMPANY_ADDRESS'),
  569. 'vat' => config('SETTINGS::INVOICE:COMPANY_VAT'),
  570. 'custom_fields' => [
  571. 'E-Mail' => config('SETTINGS::INVOICE:COMPANY_MAIL'),
  572. 'Web' => config('SETTINGS::INVOICE:COMPANY_WEBSITE'),
  573. ],
  574. ]);
  575. $customer = new Buyer([
  576. 'name' => $user->name,
  577. 'custom_fields' => [
  578. 'E-Mail' => $user->email,
  579. 'Client ID' => $user->id,
  580. ],
  581. ]);
  582. $item = (new InvoiceItem())
  583. ->title($shopProduct->description)
  584. ->pricePerUnit($shopProduct->price);
  585. $notes = [
  586. __('Payment method').': '.$payment->payment_method,
  587. ];
  588. $notes = implode('<br>', $notes);
  589. $invoice = Invoice::make()
  590. ->template('controlpanel')
  591. ->name(__('Invoice'))
  592. ->buyer($customer)
  593. ->seller($seller)
  594. ->discountByPercent(PartnerDiscount::getDiscount())
  595. ->taxRate(floatval($shopProduct->getTaxPercent()))
  596. ->shipping(0)
  597. ->addItem($item)
  598. ->status(__($paymentStatus))
  599. ->series(now()->format('mY'))
  600. ->delimiter('-')
  601. ->sequence($newInvoiceID)
  602. ->serialNumberFormat(config('SETTINGS::INVOICE:PREFIX').'{DELIMITER}{SERIES}{SEQUENCE}')
  603. ->currencyCode($currencyCode)
  604. ->currencySymbol(Currencies::getSymbol($currencyCode))
  605. ->notes($notes);
  606. if (file_exists($logoPath)) {
  607. $invoice->logo($logoPath);
  608. }
  609. //Save the invoice in "storage\app\invoice\USER_ID\YEAR"
  610. $invoice->filename = $invoice->getSerialNumber().'.pdf';
  611. $invoice->render();
  612. Storage::disk('local')->put('invoice/'.$user->id.'/'.now()->format('Y').'/'.$invoice->filename, $invoice->output);
  613. \App\Models\Invoice::create([
  614. 'invoice_user' => $user->id,
  615. 'invoice_name' => $invoice->getSerialNumber(),
  616. 'payment_id' => $payment->payment_id,
  617. ]);
  618. //Send Invoice per Mail
  619. $user->notify(new InvoiceNotification($invoice, $user, $payment));
  620. }
  621. public function checkAmount($amount, $currencyCode, $payment_method)
  622. {
  623. $minimums = [
  624. "USD" => [
  625. "paypal" => 0,
  626. "stripe" => 0.5
  627. ],
  628. "AED" => [
  629. "paypal" => 0,
  630. "stripe" => 2
  631. ],
  632. "AUD" => [
  633. "paypal" => 0,
  634. "stripe" => 0.5
  635. ],
  636. "BGN" => [
  637. "paypal" => 0,
  638. "stripe" => 1
  639. ],
  640. "BRL" => [
  641. "paypal" => 0,
  642. "stripe" => 0.5
  643. ],
  644. "CAD" => [
  645. "paypal" => 0,
  646. "stripe" => 0.5
  647. ],
  648. "CHF" => [
  649. "paypal" => 0,
  650. "stripe" => 0.5
  651. ],
  652. "CZK" => [
  653. "paypal" => 0,
  654. "stripe" => 15
  655. ],
  656. "DKK" => [
  657. "paypal" => 0,
  658. "stripe" => 2.5
  659. ],
  660. "EUR" => [
  661. "paypal" => 0,
  662. "stripe" => 0.5
  663. ],
  664. "GBP" => [
  665. "paypal" => 0,
  666. "stripe" => 0.3
  667. ],
  668. "HKD" => [
  669. "paypal" => 0,
  670. "stripe" => 4
  671. ],
  672. "HRK" => [
  673. "paypal" => 0,
  674. "stripe" => 0.5
  675. ],
  676. "HUF" => [
  677. "paypal" => 0,
  678. "stripe" => 175
  679. ],
  680. "INR" => [
  681. "paypal" => 0,
  682. "stripe" => 0.5
  683. ],
  684. "JPY" => [
  685. "paypal" => 0,
  686. "stripe" => 0.5
  687. ],
  688. "MXN" => [
  689. "paypal" => 0,
  690. "stripe" => 10
  691. ],
  692. "MYR" => [
  693. "paypal" => 0,
  694. "stripe" => 2
  695. ],
  696. "NOK" => [
  697. "paypal" => 0,
  698. "stripe" => 3
  699. ],
  700. "NZD" => [
  701. "paypal" => 0,
  702. "stripe" => 0.5
  703. ],
  704. "PLN" => [
  705. "paypal" => 0,
  706. "stripe" => 2
  707. ],
  708. "RON" => [
  709. "paypal" => 0,
  710. "stripe" => 2
  711. ],
  712. "SEK" => [
  713. "paypal" => 0,
  714. "stripe" => 3
  715. ],
  716. "SGD" => [
  717. "paypal" => 0,
  718. "stripe" => 0.5
  719. ],
  720. "THB" => [
  721. "paypal" => 0,
  722. "stripe" => 10
  723. ]
  724. ];
  725. return $amount >= $minimums[$currencyCode][$payment_method];
  726. }
  727. /**
  728. * @return JsonResponse|mixed
  729. *
  730. * @throws Exception
  731. */
  732. public function dataTable()
  733. {
  734. $query = Payment::with('user');
  735. return datatables($query)
  736. ->addColumn('user', function (Payment $payment) {
  737. return
  738. ($payment->user)?'<a href="'.route('admin.users.show', $payment->user->id).'">'.$payment->user->name.'</a>':__('Unknown user');
  739. })
  740. ->editColumn('price', function (Payment $payment) {
  741. return $payment->formatToCurrency($payment->price);
  742. })
  743. ->editColumn('tax_value', function (Payment $payment) {
  744. return $payment->formatToCurrency($payment->tax_value);
  745. })
  746. ->editColumn('tax_percent', function (Payment $payment) {
  747. return $payment->tax_percent.' %';
  748. })
  749. ->editColumn('total_price', function (Payment $payment) {
  750. return $payment->formatToCurrency($payment->total_price);
  751. })
  752. ->editColumn('created_at', function (Payment $payment) {
  753. return ['display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
  754. 'raw' => $payment->created_at ? strtotime($payment->created_at) : ''];
  755. })
  756. ->addColumn('actions', function (Payment $payment) {
  757. 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>';
  758. })
  759. ->rawColumns(['actions', 'user'])
  760. ->make(true);
  761. }
  762. }