CheckoutController.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. namespace App\Http\Controllers\Front;
  3. use App\Shop\Addresses\Repositories\Interfaces\AddressRepositoryInterface;
  4. use App\Shop\Cart\Requests\CartCheckoutRequest;
  5. use App\Shop\Carts\Repositories\Interfaces\CartRepositoryInterface;
  6. use App\Shop\Carts\Requests\PayPalCheckoutExecutionRequest;
  7. use App\Shop\Carts\Requests\StripeExecutionRequest;
  8. use App\Shop\Couriers\Repositories\Interfaces\CourierRepositoryInterface;
  9. use App\Shop\Customers\Customer;
  10. use App\Shop\Customers\Repositories\CustomerRepository;
  11. use App\Shop\Customers\Repositories\Interfaces\CustomerRepositoryInterface;
  12. use App\Shop\Orders\Repositories\Interfaces\OrderRepositoryInterface;
  13. use App\Shop\PaymentMethods\Paypal\Exceptions\PaypalRequestError;
  14. use App\Shop\PaymentMethods\Paypal\Repositories\PayPalExpressCheckoutRepository;
  15. use App\Shop\PaymentMethods\Stripe\Exceptions\StripeChargingErrorException;
  16. use App\Shop\PaymentMethods\Stripe\StripeRepository;
  17. use App\Shop\Products\Repositories\Interfaces\ProductRepositoryInterface;
  18. use App\Shop\Products\Transformations\ProductTransformable;
  19. use App\Shop\Shipping\ShippingInterface;
  20. use Exception;
  21. use App\Http\Controllers\Controller;
  22. use Gloudemans\Shoppingcart\Facades\Cart;
  23. use Illuminate\Http\Request;
  24. use Illuminate\Support\Collection;
  25. use Illuminate\Support\Facades\Log;
  26. use PayPal\Exception\PayPalConnectionException;
  27. class CheckoutController extends Controller
  28. {
  29. use ProductTransformable;
  30. /**
  31. * @var CartRepositoryInterface
  32. */
  33. private $cartRepo;
  34. /**
  35. * @var CourierRepositoryInterface
  36. */
  37. private $courierRepo;
  38. /**
  39. * @var AddressRepositoryInterface
  40. */
  41. private $addressRepo;
  42. /**
  43. * @var CustomerRepositoryInterface
  44. */
  45. private $customerRepo;
  46. /**
  47. * @var ProductRepositoryInterface
  48. */
  49. private $productRepo;
  50. /**
  51. * @var OrderRepositoryInterface
  52. */
  53. private $orderRepo;
  54. /**
  55. * @var PayPalExpressCheckoutRepository
  56. */
  57. private $payPal;
  58. /**
  59. * @var ShippingInterface
  60. */
  61. private $shippingRepo;
  62. public function __construct(
  63. CartRepositoryInterface $cartRepository,
  64. CourierRepositoryInterface $courierRepository,
  65. AddressRepositoryInterface $addressRepository,
  66. CustomerRepositoryInterface $customerRepository,
  67. ProductRepositoryInterface $productRepository,
  68. OrderRepositoryInterface $orderRepository,
  69. ShippingInterface $shipping
  70. ) {
  71. $this->cartRepo = $cartRepository;
  72. $this->courierRepo = $courierRepository;
  73. $this->addressRepo = $addressRepository;
  74. $this->customerRepo = $customerRepository;
  75. $this->productRepo = $productRepository;
  76. $this->orderRepo = $orderRepository;
  77. $this->payPal = new PayPalExpressCheckoutRepository;
  78. $this->shippingRepo = $shipping;
  79. }
  80. /**
  81. * Display a listing of the resource.
  82. *
  83. * @param Request $request
  84. *
  85. * @return \Illuminate\Http\Response
  86. */
  87. public function index(Request $request)
  88. {
  89. $products = $this->cartRepo->getCartItems();
  90. $customer = $request->user();
  91. $rates = null;
  92. $shipment_object_id = null;
  93. if (env('ACTIVATE_SHIPPING') == 1) {
  94. $shipment = $this->createShippingProcess($customer, $products);
  95. if (!is_null($shipment)) {
  96. $shipment_object_id = $shipment->object_id;
  97. $rates = $shipment->rates;
  98. }
  99. }
  100. // Get payment gateways
  101. $paymentGateways = collect(explode(',', config('payees.name')))->transform(function ($name) {
  102. return config($name);
  103. })->all();
  104. $billingAddress = $customer->addresses()->first();
  105. return view('front.checkout', [
  106. 'customer' => $customer,
  107. 'billingAddress' => $billingAddress,
  108. 'addresses' => $customer->addresses()->get(),
  109. 'products' => $this->cartRepo->getCartItems(),
  110. 'subtotal' => $this->cartRepo->getSubTotal(),
  111. 'tax' => $this->cartRepo->getTax(),
  112. 'total' => $this->cartRepo->getTotal(2),
  113. 'payments' => $paymentGateways,
  114. 'cartItems' => $this->cartRepo->getCartItemsTransformed(),
  115. 'shipment_object_id' => $shipment_object_id,
  116. 'rates' => $rates
  117. ]);
  118. }
  119. /**
  120. * Checkout the items
  121. *
  122. * @param CartCheckoutRequest $request
  123. *
  124. * @return \Illuminate\Http\RedirectResponse
  125. * @throws \App\Shop\Addresses\Exceptions\AddressNotFoundException
  126. * @throws \App\Shop\Customers\Exceptions\CustomerPaymentChargingErrorException
  127. * @codeCoverageIgnore
  128. */
  129. public function store(CartCheckoutRequest $request)
  130. {
  131. $shippingFee = 0;
  132. switch ($request->input('payment')) {
  133. case 'paypal':
  134. return $this->payPal->process($shippingFee, $request);
  135. break;
  136. case 'stripe':
  137. $details = [
  138. 'description' => 'Stripe payment',
  139. 'metadata' => $this->cartRepo->getCartItems()->all()
  140. ];
  141. $customer = $this->customerRepo->findCustomerById(auth()->id());
  142. $customerRepo = new CustomerRepository($customer);
  143. $customerRepo->charge($this->cartRepo->getTotal(2, $shippingFee), $details);
  144. break;
  145. default:
  146. }
  147. }
  148. /**
  149. * Execute the PayPal payment
  150. *
  151. * @param PayPalCheckoutExecutionRequest $request
  152. * @return \Illuminate\Http\RedirectResponse
  153. */
  154. public function executePayPalPayment(PayPalCheckoutExecutionRequest $request)
  155. {
  156. try {
  157. $this->payPal->execute($request);
  158. $this->cartRepo->clearCart();
  159. return redirect()->route('checkout.success');
  160. } catch (PayPalConnectionException $e) {
  161. throw new PaypalRequestError($e->getData());
  162. } catch (Exception $e) {
  163. throw new PaypalRequestError($e->getMessage());
  164. }
  165. }
  166. /**
  167. * @param StripeExecutionRequest $request
  168. * @return \Stripe\Charge
  169. */
  170. public function charge(StripeExecutionRequest $request)
  171. {
  172. try {
  173. $customer = $this->customerRepo->findCustomerById(auth()->id());
  174. $stripeRepo = new StripeRepository($customer);
  175. $stripeRepo->execute(
  176. $request->all(),
  177. Cart::total(),
  178. Cart::tax()
  179. );
  180. return redirect()->route('checkout.success')->with('message', 'Stripe payment successful!');
  181. } catch (StripeChargingErrorException $e) {
  182. Log::info($e->getMessage());
  183. return redirect()->route('checkout.index')->with('error', 'There is a problem processing your request.');
  184. }
  185. }
  186. /**
  187. * Cancel page
  188. *
  189. * @param Request $request
  190. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  191. */
  192. public function cancel(Request $request)
  193. {
  194. return view('front.checkout-cancel', ['data' => $request->all()]);
  195. }
  196. /**
  197. * Success page
  198. *
  199. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  200. */
  201. public function success()
  202. {
  203. return view('front.checkout-success');
  204. }
  205. /**
  206. * @param Customer $customer
  207. * @param Collection $products
  208. *
  209. * @return mixed
  210. */
  211. private function createShippingProcess(Customer $customer, Collection $products)
  212. {
  213. $customerRepo = new CustomerRepository($customer);
  214. if ($customerRepo->findAddresses()->count() > 0 && $products->count() > 0) {
  215. $this->shippingRepo->setPickupAddress();
  216. $deliveryAddress = $customerRepo->findAddresses()->first();
  217. $this->shippingRepo->setDeliveryAddress($deliveryAddress);
  218. $this->shippingRepo->readyParcel($this->cartRepo->getCartItems());
  219. return $this->shippingRepo->readyShipment();
  220. }
  221. }
  222. }