2020-09-23 11:10:21 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Webkul\Paypal\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
use Webkul\Checkout\Facades\Cart;
|
2020-11-18 13:10:29 +00:00
|
|
|
use Webkul\Paypal\Payment\SmartButton;
|
2020-09-23 11:10:21 +00:00
|
|
|
use Webkul\Sales\Repositories\OrderRepository;
|
|
|
|
|
use Webkul\Sales\Repositories\InvoiceRepository;
|
|
|
|
|
|
|
|
|
|
class SmartButtonController extends Controller
|
|
|
|
|
{
|
2020-11-18 13:10:29 +00:00
|
|
|
/**
|
2021-02-05 09:14:51 +00:00
|
|
|
* SmartButton $smartButton
|
2020-11-18 13:10:29 +00:00
|
|
|
*
|
|
|
|
|
* @var \Webkul\Paypal\Payment\SmartButton
|
|
|
|
|
*/
|
2021-02-05 09:14:51 +00:00
|
|
|
protected $smartButton;
|
2020-11-18 13:10:29 +00:00
|
|
|
|
2020-09-23 11:10:21 +00:00
|
|
|
/**
|
2021-02-05 09:14:51 +00:00
|
|
|
* OrderRepository $orderRepository
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @var \Webkul\Sales\Repositories\OrderRepository
|
|
|
|
|
*/
|
|
|
|
|
protected $orderRepository;
|
|
|
|
|
|
|
|
|
|
/**
|
2021-02-05 09:14:51 +00:00
|
|
|
* InvoiceRepository $invoiceRepository
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @var \Webkul\Sales\Repositories\InvoiceRepository
|
|
|
|
|
*/
|
|
|
|
|
protected $invoiceRepository;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new controller instance.
|
|
|
|
|
*
|
2021-02-05 09:14:51 +00:00
|
|
|
* @param \Webkul\Paypal\Payment\SmartButton $smartButton
|
2020-09-23 11:10:21 +00:00
|
|
|
* @param \Webkul\Attribute\Repositories\OrderRepository $orderRepository
|
|
|
|
|
* @param \Webkul\Sales\Repositories\InvoiceRepository $invoiceRepository
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function __construct(
|
2021-02-05 09:14:51 +00:00
|
|
|
SmartButton $smartButton,
|
2020-09-23 11:10:21 +00:00
|
|
|
OrderRepository $orderRepository,
|
|
|
|
|
InvoiceRepository $invoiceRepository
|
|
|
|
|
)
|
|
|
|
|
{
|
2021-02-05 09:14:51 +00:00
|
|
|
$this->smartButton = $smartButton;
|
|
|
|
|
|
2020-09-23 11:10:21 +00:00
|
|
|
$this->orderRepository = $orderRepository;
|
|
|
|
|
|
|
|
|
|
$this->invoiceRepository = $invoiceRepository;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-02-04 13:43:59 +00:00
|
|
|
* Paypal order creation for approval of client.
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
|
|
*/
|
2021-02-05 09:14:51 +00:00
|
|
|
public function createOrder()
|
2020-11-18 13:10:29 +00:00
|
|
|
{
|
2021-02-05 09:32:34 +00:00
|
|
|
try {
|
|
|
|
|
return response()->json($this->smartButton->createOrder($this->buildRequestBody()));
|
|
|
|
|
} catch (\Exception $e) {
|
2021-02-22 12:16:09 +00:00
|
|
|
return response()->json(json_decode($e->getMessage()), 400);
|
2021-02-05 09:32:34 +00:00
|
|
|
}
|
2020-11-18 13:10:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-02-05 09:14:51 +00:00
|
|
|
* Capturing paypal order after approval.
|
2020-11-18 13:10:29 +00:00
|
|
|
*
|
|
|
|
|
* @return \Illuminate\Http\Response
|
|
|
|
|
*/
|
2021-02-04 13:43:59 +00:00
|
|
|
public function captureOrder()
|
2020-11-18 13:10:29 +00:00
|
|
|
{
|
2021-02-05 09:32:34 +00:00
|
|
|
try {
|
|
|
|
|
$this->smartButton->captureOrder(request()->input('orderData.orderID'));
|
|
|
|
|
return $this->saveOrder();
|
|
|
|
|
} catch (\Exception $e) {
|
2021-02-22 12:16:09 +00:00
|
|
|
return response()->json(json_decode($e->getMessage()), 400);
|
2021-02-05 09:32:34 +00:00
|
|
|
}
|
2020-11-18 13:10:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Build request body.
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
protected function buildRequestBody()
|
2020-09-23 11:10:21 +00:00
|
|
|
{
|
|
|
|
|
$cart = Cart::getCart();
|
|
|
|
|
|
|
|
|
|
$billingAddressLines = $this->getAddressLines($cart->billing_address->address1);
|
|
|
|
|
|
|
|
|
|
$data = [
|
|
|
|
|
'intent' => 'CAPTURE',
|
|
|
|
|
|
|
|
|
|
'payer' => [
|
|
|
|
|
'name' => [
|
|
|
|
|
'given_name' => $cart->billing_address->first_name,
|
|
|
|
|
'surname' => $cart->billing_address->last_name,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'address' => [
|
|
|
|
|
'address_line_1' => current($billingAddressLines),
|
|
|
|
|
'address_line_2' => last($billingAddressLines),
|
|
|
|
|
'admin_area_2' => $cart->billing_address->city,
|
|
|
|
|
'admin_area_1' => $cart->billing_address->state,
|
|
|
|
|
'postal_code' => $cart->billing_address->postcode,
|
|
|
|
|
'country_code' => $cart->billing_address->country,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'email_address' => $cart->billing_address->email,
|
|
|
|
|
|
|
|
|
|
'phone' => [
|
|
|
|
|
'phone_type' => 'MOBILE',
|
|
|
|
|
|
|
|
|
|
'phone_number' => [
|
|
|
|
|
'national_number' => $cart->billing_address->phone,
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'application_context' => [
|
2020-11-02 12:03:57 +00:00
|
|
|
'shipping_preference' => 'SET_PROVIDED_ADDRESS',
|
2020-09-23 11:10:21 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'purchase_units' => [
|
|
|
|
|
[
|
|
|
|
|
'amount' => [
|
|
|
|
|
'value' => (float) $cart->sub_total + $cart->tax_total + ($cart->selected_shipping_rate ? $cart->selected_shipping_rate->price : 0) - $cart->discount_amount,
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
|
|
|
|
|
'breakdown' => [
|
|
|
|
|
'item_total' => [
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
'value' => (float) $cart->sub_total,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'shipping' => [
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
'value' => (float) ($cart->selected_shipping_rate ? $cart->selected_shipping_rate->price : 0),
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'tax_total' => [
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
'value' => (float) $cart->tax_total,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'discount' => [
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
'value' => (float) $cart->discount_amount,
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
'items' => $this->getLineItems($cart),
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($cart->haveStockableItems() && $cart->shipping_address) {
|
|
|
|
|
$data['purchase_units'][0] = array_merge($data['purchase_units'][0], [
|
|
|
|
|
'shipping' => [
|
|
|
|
|
'address' => [
|
|
|
|
|
'address_line_1' => current($billingAddressLines),
|
|
|
|
|
'address_line_2' => last($billingAddressLines),
|
|
|
|
|
'admin_area_2' => $cart->shipping_address->city,
|
|
|
|
|
'admin_area_1' => $cart->shipping_address->state,
|
|
|
|
|
'postal_code' => $cart->shipping_address->postcode,
|
|
|
|
|
'country_code' => $cart->shipping_address->country,
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-11-18 13:10:29 +00:00
|
|
|
* Return cart items.
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @param string $cart
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2020-11-18 13:10:29 +00:00
|
|
|
protected function getLineItems($cart)
|
2020-09-23 11:10:21 +00:00
|
|
|
{
|
|
|
|
|
$lineItems = [];
|
|
|
|
|
|
|
|
|
|
foreach ($cart->items as $item) {
|
|
|
|
|
$lineItems[] = [
|
|
|
|
|
'unit_amount' => [
|
|
|
|
|
'currency_code' => $cart->cart_currency_code,
|
|
|
|
|
'value' => (float) $item->price,
|
|
|
|
|
],
|
|
|
|
|
'quantity' => $item->quantity,
|
|
|
|
|
'name' => $item->name,
|
|
|
|
|
'sku' => $item->sku,
|
2020-11-02 12:03:57 +00:00
|
|
|
'category' => $item->product->getTypeInstance()->isStockable() ? 'PHYSICAL_GOODS' : 'DIGITAL_GOODS',
|
2020-09-23 11:10:21 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $lineItems;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-11-18 13:10:29 +00:00
|
|
|
* Return convert multiple address lines into 2 address lines.
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @param string $address
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2020-11-18 13:10:29 +00:00
|
|
|
protected function getAddressLines($address)
|
2020-09-23 11:10:21 +00:00
|
|
|
{
|
|
|
|
|
$address = explode(PHP_EOL, $address, 2);
|
|
|
|
|
|
|
|
|
|
$addressLines = [current($address)];
|
|
|
|
|
|
|
|
|
|
if (isset($address[1])) {
|
|
|
|
|
$addressLines[] = str_replace(["\r\n", "\r", "\n"], ' ', last($address));
|
|
|
|
|
} else {
|
|
|
|
|
$addressLines[] = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $addressLines;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 13:43:59 +00:00
|
|
|
/**
|
|
|
|
|
* Saving order once captured and all formalities done.
|
|
|
|
|
*
|
|
|
|
|
* @return \Illuminate\Http\Response
|
|
|
|
|
*/
|
|
|
|
|
protected function saveOrder()
|
|
|
|
|
{
|
|
|
|
|
if (Cart::hasError()) {
|
|
|
|
|
return response()->json(['redirect_url' => route('shop.checkout.cart.index')], 403);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Cart::collectTotals();
|
|
|
|
|
|
|
|
|
|
$this->validateOrder();
|
|
|
|
|
|
|
|
|
|
$order = $this->orderRepository->create(Cart::prepareDataForOrder());
|
|
|
|
|
|
|
|
|
|
$this->orderRepository->update(['status' => 'processing'], $order->id);
|
|
|
|
|
|
|
|
|
|
if ($order->canInvoice()) {
|
|
|
|
|
$this->invoiceRepository->create($this->prepareInvoiceData($order));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Cart::deActivateCart();
|
|
|
|
|
|
|
|
|
|
session()->flash('order', $order);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'success' => true,
|
|
|
|
|
]);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
session()->flash('error', trans('shop::app.common.error'));
|
|
|
|
|
|
|
|
|
|
throw $e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-23 11:10:21 +00:00
|
|
|
/**
|
2020-11-18 13:10:29 +00:00
|
|
|
* Prepares order's invoice data for creation.
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @param \Webkul\Sales\Models\Order $order
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
protected function prepareInvoiceData($order)
|
|
|
|
|
{
|
|
|
|
|
$invoiceData = ["order_id" => $order->id,];
|
|
|
|
|
|
|
|
|
|
foreach ($order->items as $item) {
|
|
|
|
|
$invoiceData['invoice']['items'][$item->id] = $item->qty_to_invoice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $invoiceData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-11-18 13:10:29 +00:00
|
|
|
* Validate order before creation.
|
2020-09-23 11:10:21 +00:00
|
|
|
*
|
|
|
|
|
* @return void|\Exception
|
|
|
|
|
*/
|
2020-11-18 13:10:29 +00:00
|
|
|
protected function validateOrder()
|
2020-09-23 11:10:21 +00:00
|
|
|
{
|
|
|
|
|
$cart = Cart::getCart();
|
|
|
|
|
|
2021-02-12 05:52:22 +00:00
|
|
|
$minimumOrderAmount = (float) core()->getConfigData('sales.orderSettings.minimum-order.minimum_order_amount') ?? 0;
|
2020-11-18 13:10:29 +00:00
|
|
|
|
|
|
|
|
if (! $cart->checkMinimumOrder()) {
|
|
|
|
|
throw new \Exception(trans('shop::app.checkout.cart.minimum-order-message', ['amount' => core()->currency($minimumOrderAmount)]));
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-23 11:10:21 +00:00
|
|
|
if ($cart->haveStockableItems() && ! $cart->shipping_address) {
|
|
|
|
|
throw new \Exception(trans('Please check shipping address.'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! $cart->billing_address) {
|
|
|
|
|
throw new \Exception(trans('Please check billing address.'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($cart->haveStockableItems() && ! $cart->selected_shipping_rate) {
|
|
|
|
|
throw new \Exception(trans('Please specify shipping method.'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! $cart->payment) {
|
|
|
|
|
throw new \Exception(trans('Please specify payment method.'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|