Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
Implemented Hosted checkout
Browse files Browse the repository at this point in the history
  • Loading branch information
lucionescu committed Sep 5, 2023
1 parent 5d927cc commit e341b92
Show file tree
Hide file tree
Showing 113 changed files with 2,645 additions and 8,481 deletions.
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "lunar/plugin-shopware-6",
"description": "Secure payment with credit card via Lunar",
"version": "1.1.0",
"version": "2.0.0",
"type": "shopware-platform-plugin",
"license": "MIT",
"authors": [
Expand All @@ -11,10 +11,10 @@
}
],
"require": {
"php": ">=8.0",
"shopware/core": "^6.4 | ^6.5",
"shopware/administration": "^6.4 | ^6.5",
"shopware/storefront": "^6.4 | ^6.5",
"paylike/php-api": "^2.0"
"shopware/storefront": "^6.4 | ^6.5"
},
"extra": {
"shopware-plugin-class": "Lunar\\Payment\\LunarPayment",
Expand Down
227 changes: 28 additions & 199 deletions src/Controller/OrderTransactionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Core\System\StateMachine\StateMachineRegistry;
Expand All @@ -17,10 +16,7 @@
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler;

use Paylike\Paylike as ApiClient;
use Lunar\Payment\Helpers\OrderHelper;
use Lunar\Payment\Helpers\PluginHelper;
use Lunar\Payment\Helpers\CurrencyHelper;
use Lunar\Payment\Helpers\LogHelper as Logger;

/**
Expand All @@ -30,50 +26,22 @@
*/
class OrderTransactionController extends AbstractController
{
private const CONFIG_PATH = PluginHelper::PLUGIN_CONFIG_PATH;

/** @var EntityRepository */
private $stateMachineHistory;

/** @var StateMachineRegistry */
private $stateMachineRegistry;

/** @var OrderTransactionStateHandler */
private $transactionStateHandler;

/** @var EntityRepository */
private $lunarTransactionRepository;

/** @var OrderHelper */
private $orderHelper;

/** @var SystemConfigService */
private $systemConfigService;

/** @var Logger */
private $logger;


/**
* Constructor
*/
public function __construct(
EntityRepository $stateMachineHistory,
StateMachineRegistry $stateMachineRegistry,
OrderTransactionStateHandler $transactionStateHandler,
EntityRepository $lunarTransactionRepository,
OrderHelper $orderHelper,
SystemConfigService $systemConfigService,
Logger $logger
)
{
private EntityRepository $stateMachineHistory,
private StateMachineRegistry $stateMachineRegistry,
private OrderTransactionStateHandler $transactionStateHandler,
private EntityRepository $lunarTransactionRepository,
private SystemConfigService $systemConfigService,
private Logger $logger,
private OrderHelper $orderHelper
) {
$this->stateMachineHistory = $stateMachineHistory;
$this->stateMachineRegistry = $stateMachineRegistry;
$this->transactionStateHandler = $transactionStateHandler;
$this->lunarTransactionRepository = $lunarTransactionRepository;
$this->orderHelper = $orderHelper;
$this->systemConfigService = $systemConfigService;
$this->logger = $logger;
$this->orderHelper = $orderHelper;
}

/**
Expand All @@ -97,163 +65,50 @@ public function refund(Request $request, Context $context): JsonResponse
}

/**
* VOID / CANCEL
* CANCEL
*
* @Route("/api/lunar/void", name="api.action.lunar.void", methods={"POST"})
* @Route("/api/lunar/cancel", name="api.action.lunar.cancel", methods={"POST"})
*/
public function void(Request $request, Context $context): JsonResponse
public function cancel(Request $request, Context $context): JsonResponse
{
return $this->processPaymentAction($request, $context, 'void');
return $this->processPaymentAction($request, $context, 'cancel');
}


/**
* @TODO unify code with that from \Subscriber\OrderTransactionStateChangeSubscriber.php
*
*/
private function processPaymentAction(
Request $request,
Context $context,
string $actionType
): JsonResponse
{
Request $request,
Context $context,
string $actionType
): JsonResponse {

switch ($actionType) {
case OrderHelper::CAPTURE_STATUS:
$lunarTransactionState = OrderHelper::AUTHORIZE_STATUS;
$orderTransactionStateToCheck = OrderHelper::TRANSACTION_AUTHORIZED;
$orderTransactionAction = OrderHelper::TRANSACTION_PAID;
$amountToCheck = 'pendingAmount';
case OrderHelper::CAPTURE:
$transactionAction = OrderHelper::TRANSACTION_PAID;
break;
case OrderHelper::REFUND_STATUS:
$lunarTransactionState = OrderHelper::CAPTURE_STATUS;
$orderTransactionStateToCheck = OrderHelper::TRANSACTION_PAID;
$orderTransactionAction = OrderHelper::TRANSACTION_REFUND;
$amountToCheck = 'capturedAmount';
case OrderHelper::REFUND:
$transactionAction = OrderHelper::TRANSACTION_REFUND;
break;
case OrderHelper::VOID_STATUS:
$lunarTransactionState = OrderHelper::AUTHORIZE_STATUS;
$orderTransactionStateToCheck = OrderHelper::TRANSACTION_AUTHORIZED;
$orderTransactionAction = OrderHelper::TRANSACTION_VOID;
$amountToCheck = 'pendingAmount';
case OrderHelper::CANCEL:
$transactionAction = OrderHelper::TRANSACTION_CANCEL;
break;
}

$actionType = ucfirst($actionType);
$actionTypeAllCaps = strtoupper($actionType);

$params = $request->request->all()['params'];
$orderId = $params['orderId'];
$lunarTransactionId = $params['lunarTransactionId'];

try {
$order = $this->orderHelper->getOrderById($orderId, $context);

$lastOrderTransaction = $order->transactions->last();

$transactionStateName = $lastOrderTransaction->getStateMachineState()->technicalName;

/**
* Get lunar transaction
*/
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('orderId', $orderId));
$criteria->addFilter(new EqualsFilter('transactionType', $lunarTransactionState));

$lunarTransaction = $this->lunarTransactionRepository->search($criteria, $context)->first();

if (!$lunarTransaction || $orderTransactionStateToCheck != $transactionStateName) {
return new JsonResponse([
'status' => false,
'message' => 'Error',
'code' => 0,
'errors'=> [$actionType . ' failed. Not lunar transaction or payment not ' . $orderTransactionStateToCheck],
], 400);
}

/**
* Instantiate Api Client
* Fetch transaction
* Check amount & currency
* Proceed with payment capture
*/
$privateApiKey = $this->getApiKey($order);
$apiClient = new ApiClient($privateApiKey);
$fetchedTransaction = $apiClient->transactions()->fetch($lunarTransactionId);

if (!$fetchedTransaction) {
return new JsonResponse([
'status' => false,
'message' => 'Error',
'code' => 0,
'errors'=> ['Fetch transaction failed'],
], 400);
}

$totalPrice = $lastOrderTransaction->amount->getTotalPrice();
$currencyCode = $order->getCurrency()->isoCode;
$amountInMinor = (int) CurrencyHelper::getAmountInMinor($currencyCode, $totalPrice);

if ($fetchedTransaction['amount'] !== $amountInMinor) {
$errors[] = 'Fetch transaction failed: amount mismatch';
}
if ($fetchedTransaction['currency'] !== $currencyCode) {
$errors[] = 'Fetch transaction failed: currency mismatch';
}

if ($fetchedTransaction[$amountToCheck] !== $amountInMinor) {
$errors[] = 'Fetch transaction failed: ' . $amountToCheck . ' mismatch';
}

$transactionData = [
'amount' => $amountInMinor,
'currency' => $currencyCode,
];

$result['successful'] = false;
$lastOrderTransaction = $order->transactions->last(); // @TODO check this if needs first()

/**
* API Transaction call: capture/refund/void
* Change order transaction state.
* The event will be processed in Lunar\Payment\Subscriber\OrderTransactionStateChangeSubscriber
*/
$result = $apiClient->transactions()->{$actionType}($lunarTransactionId, $transactionData);

$this->logger->writeLog([$actionTypeAllCaps . ' request data: ', $transactionData]);

if (true !== $result['successful']) {
$this->logger->writeLog([$actionTypeAllCaps . ' error (admin): ', $result]);
$errors[] = $actionType . ' transaction api action failed';
}


$lastLunarOperation = end($result['trail']);
$transactionAmount = $lastLunarOperation['amount'];
$transactionAmount = CurrencyHelper::getAmountInMajor($currencyCode, $transactionAmount);

$transactionData = [
[
'orderId' => $orderId,
'transactionId' => $lunarTransactionId,
'transactionType' => strtolower($actionType),
'transactionCurrency' => $currencyCode,
'orderAmount' => $totalPrice,
'transactionAmount' => $transactionAmount,
'amountInMinor' => $amountInMinor,
'createdAt' => date(Defaults::STORAGE_DATE_TIME_FORMAT),
],
];


/** Change order transaction state. */
$this->transactionStateHandler->{$orderTransactionAction}($lastOrderTransaction->id, $context);

/** Change order state. */
OrderHelper::changeOrderState($orderId, strtolower($actionType), $context, $this->stateMachineRegistry);


/** Insert new data to database and log it. */
$this->lunarTransactionRepository->create($transactionData, $context);

$this->logger->writeLog(['Succes: ', $transactionData[0]]);
$this->transactionStateHandler->{$transactionAction}($lastOrderTransaction->id, $context);

} catch (\Exception $e) {
$errors[] = 'An exception occured. Please try again. If this persist please contact plugin developer.';
Expand All @@ -265,37 +120,16 @@ private function processPaymentAction(

if (!empty($errors)) {
return new JsonResponse([
'status' => empty($errors),
'message' => 'Error',
'code' => 0,
'errors'=> $errors ?? [],
'errors'=> $errors,
], 400);
}

return new JsonResponse([
'status' => empty($errors),
'message' => 'Success',
'code' => 0,
'errors' => $errors ?? [],
], 200);
}

/**
*
*/
private function getApiKey($order)
{
$salesChannelId = $order->getSalesChannelId();

$transactionMode = $this->systemConfigService->get(self::CONFIG_PATH . 'transactionMode', $salesChannelId);

if ($transactionMode == 'test') {
return $this->systemConfigService->get(self::CONFIG_PATH . 'testModeAppKey', $salesChannelId);
}

return $this->systemConfigService->get(self::CONFIG_PATH . 'liveModeAppKey', $salesChannelId);
}

/**
* FETCH TRANSACTIONS
*
Expand All @@ -322,18 +156,13 @@ public function fetchTransactions(Request $request, Context $context): JsonRespo

if (!empty($errors)) {
return new JsonResponse([
'status' => empty($errors),
'message' => 'Error',
'code' => 0,
'errors' => $errors,
], 404);
}

return new JsonResponse([
'status' => empty($errors),
'message' => 'Success',
'code' => 0,
'errors' => $errors,
'transactions' => $lunarTransactions->getElements(),
], 200);
}
Expand Down
Loading

0 comments on commit e341b92

Please sign in to comment.