194 lines
7.4 KiB
PHP
194 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace KupShop\PayPalCheckoutBundle\Controller;
|
|
|
|
use KupShop\KupShopBundle\Context\CountryContext;
|
|
use KupShop\KupShopBundle\Context\CurrencyContext;
|
|
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
|
|
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
|
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
|
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
|
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
|
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
|
use PayPalCheckoutSdk\Orders\OrdersGetRequest;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
|
|
/**
|
|
* !!!
|
|
* composer require paypal/paypal-checkout-sdk.
|
|
*/
|
|
class PayPalCheckoutController extends AbstractController
|
|
{
|
|
/** @var CurrencyContext */
|
|
protected $currencyContext;
|
|
|
|
/** @var CountryContext */
|
|
protected $countryContext;
|
|
|
|
/** @var SentryLogger */
|
|
protected $logger;
|
|
|
|
/** @var \PayPalCheckout */
|
|
protected $payPalCheckout;
|
|
|
|
public function __construct(
|
|
CurrencyContext $currencyContext,
|
|
CountryContext $countryContext,
|
|
SentryLogger $logger,
|
|
) {
|
|
$this->currencyContext = $currencyContext;
|
|
$this->countryContext = $countryContext;
|
|
$this->logger = $logger;
|
|
\Payment::includeClass('PayPalCheckout');
|
|
$this->payPalCheckout = new \PayPalCheckout();
|
|
$this->payPalCheckout->loadConfig();
|
|
}
|
|
|
|
protected function createClient(): PayPalHttpClient
|
|
{
|
|
$config = $this->payPalCheckout->config;
|
|
if (($config['mode'] ?? 'sandbox') === 'sandbox') {
|
|
$environment = new SandboxEnvironment($config['clientID'], $config['secret']);
|
|
} else {
|
|
$environment = new ProductionEnvironment($config['clientID'], $config['secret']);
|
|
}
|
|
|
|
return new PayPalHttpClient($environment);
|
|
}
|
|
|
|
/**
|
|
* @Route("/paypal-checkout/create-paypal-order/")
|
|
*
|
|
* @return Response
|
|
*/
|
|
public function createPayPalOrder(Request $request, \Cart $cart)
|
|
{
|
|
$cart->load();
|
|
$deliveryTypeID = $this->payPalCheckout->config['delivery_type_id'];
|
|
|
|
$cart->setTransport($deliveryTypeID);
|
|
// set street, email and country so cart does not break in case paypal fails
|
|
$cart->updateAddresses(
|
|
['street' => 'street', 'email' => 'email@email.com'],
|
|
['country' => $this->countryContext->getActiveId()]
|
|
);
|
|
$step = 'delivery';
|
|
$cart->findNextStep($step);
|
|
$cart->actualStep = $step;
|
|
$cart->save();
|
|
$cart->createFromDB(); // TODO: accept also hidden delivery type
|
|
|
|
try {
|
|
$inStoreError = $cart->checkCartItems();
|
|
} catch (\Exception $e) {
|
|
$inStoreError = $e->getMessage();
|
|
}
|
|
if (!empty($inStoreError)) {
|
|
$response = ['error' => $inStoreError];
|
|
|
|
return new JsonResponse($response);
|
|
}
|
|
|
|
$price = number_format($cart->totalPricePay->asFloat(), 2, '.', '');
|
|
$data = [
|
|
'intent' => 'CAPTURE',
|
|
'purchase_units' => [
|
|
[
|
|
'amount' => [
|
|
'currency_code' => $this->currencyContext->getActiveId(),
|
|
'value' => $price,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$request = new OrdersCreateRequest();
|
|
$request->prefer('return=representation');
|
|
$request->body = $data;
|
|
$response = $this->createClient()->execute($request);
|
|
|
|
return new JsonResponse($response);
|
|
}
|
|
|
|
/**
|
|
* @Route("/paypal-checkout/capture-paypal-order/{paypalOrderID}/")
|
|
*
|
|
* @return Response
|
|
*/
|
|
public function capturePayPalOrder(string $paypalOrderID, Request $request, \Cart $cart)
|
|
{
|
|
$client = $this->createClient();
|
|
$cart->load();
|
|
$cart->createFromDB();
|
|
|
|
$orderGetResponse = $client->execute(new OrdersGetRequest($paypalOrderID));
|
|
if (($orderGetResponse->result->status ?? false) === 'APPROVED') {
|
|
$address = $orderGetResponse->result->purchase_units[0]->shipping->address;
|
|
$tmpLine1 = explode(' ', $address->address_line_1);
|
|
$house = count($tmpLine1) > 1 ? array_pop($tmpLine1) : '';
|
|
$street = implode(' ', $tmpLine1);
|
|
$invoice = [
|
|
'email' => $orderGetResponse->result->payer->email_address,
|
|
'gender' => 'male',
|
|
'name' => $orderGetResponse->result->payer->name->given_name,
|
|
'surname' => $orderGetResponse->result->payer->name->surname,
|
|
'phone' => $orderGetResponse->result->payer->phone->phone_number ?? '',
|
|
'zip' => $address->postal_code,
|
|
'city' => $address->admin_area_2,
|
|
'street' => $street,
|
|
'house' => $house,
|
|
'country' => $address->country_code,
|
|
];
|
|
$invoice['phone'] = empty($invoice['phone']) ? '123456789' : $invoice['phone'];
|
|
$delivery = $invoice;
|
|
$delivery['street'] = $address->address_line_1;
|
|
unset($delivery['email'], $delivery['gender']);
|
|
$cart->updateAddresses($invoice, $delivery);
|
|
|
|
$order = $cart->submitOrder();
|
|
|
|
if (!$order instanceof \Order) {
|
|
$this->logger->captureMessage('PayPal Checkout: Failed to create kupshop order for PayPal order '.$paypalOrderID.': submitOrder() result '.json_encode($order));
|
|
addUserMessage('Failed to create order', 'danger');
|
|
redirection(createScriptURL(['s' => 'cart']));
|
|
}
|
|
|
|
// create kupshop order payment
|
|
$price = \Decimal::create($orderGetResponse->result->purchase_units[0]->amount->value);
|
|
$this->payPalCheckout->setOrder($order);
|
|
$this->payPalCheckout->createPayment($orderGetResponse->result->id, $price, [
|
|
'PayPalCheckoutController' => true,
|
|
'result' => $orderGetResponse,
|
|
]);
|
|
|
|
// capture paypal order
|
|
$captureResponse = $client->execute(new OrdersCaptureRequest($paypalOrderID));
|
|
if (($captureResponse->result->status ?? false) === 'COMPLETED') {
|
|
// capture succeeded
|
|
if (!$this->payPalCheckout->setStatus(\Payment::STATUS_FINISHED, $orderGetResponse->result->id)) {
|
|
$this->logger->captureMessage('setStatus failed!');
|
|
throw new \Exception('Set status failed');
|
|
}
|
|
// redirect to order detail
|
|
$this->payPalCheckout->success(translate('paymentSuccess', 'payment'));
|
|
}
|
|
|
|
// payment storno
|
|
if (!$this->payPalCheckout->setStatus(\Payment::STATUS_STORNO, $orderGetResponse->result->id)) {
|
|
$this->logger->captureMessage('setStatus failed!');
|
|
throw new \Exception('Set status failed');
|
|
}
|
|
// redirect to order detail
|
|
$this->payPalCheckout->error(translate('payment_storno', 'payment'));
|
|
}
|
|
|
|
$this->logger->captureMessage('PayPal Checkout: PayPal order '.$paypalOrderID.' not APPROVED!');
|
|
addUserMessage('Failed to create order', 'danger');
|
|
redirection(createScriptURL(['s' => 'cart']));
|
|
}
|
|
}
|