Hello all,
Currently, I have created a payment plugin based in the official documentation from shopware Add payment plugin.
The payment gateway in their dashboard has 3 fields to input:
- Success URL - url in which gateway redirects (in shop) after a successful transaction
- Failure URL - url in which gateway redirects (in shop) after a failed transaction
- Notify URL -url in which are stored the information regarding the transaction status and if payment is approved or not.
For every URL mentioned above, I have created them as storefront controllers.
Example: Success URL
/**
* @RouteScope(scopes={„storefront“})
* @Route(„/checkout/success“, name=„frontend.rbko.success“, methods={„GET“, „POST“}, defaults={„csrf_protected“: false})
* @param Request $request
*/
public function successPage(Request $request, Context $context, SalesChannelContext $salesChannelContext): Response
{
if (isset($_POST['TranCode'])) {
$transCode = $_POST['TranCode'];
$orderNumber = $_POST['OrderID'];
$criteria = new Criteria;
$criteria->addFilter(new EqualsFilter('orderNumber', $orderNumber));
$sql = $this->orderRepository->search($criteria, $context);
$orderID = '';
foreach ($sql as $data) {
$orderID = $data->getId();
}
$transaction = $this->getOrderTransaction($orderID, $context);
$transactionID = $transaction->getId();
if ($transCode == '000') {
$this->transactionStateHandler->paid($transactionID, $context);
}
else{
$this->transactionStateHandler->fail($transactionID, $context);
}
return $this->renderStorefront('@RBKOPayment/storefront/page/checkout/success.html.twig', [
'data' => $_POST,
'orderID' =>$orderID,
'baseURL' =>$request->getSchemeAndHttpHost()
]);
}
return $this->renderStorefront('@RBKOPayment/storefront/page/checkout/success.html.twig', [
'data' => $_POST
]);
}
Also, I have created a PaymentService which implements AsynchronousPaymentHandlerInterface.
public function pay(AsyncPaymentTransactionStruct $transaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): RedirectResponse
{
$this->logger->debug('Started');
$successUrl = $transaction->getReturnUrl();
$order = $transaction->getOrder();
$orderID = $transaction->getOrderTransaction()->getId();
$orderCustomer = $transaction->getOrder()->getOrderCustomer();
$customerEmail = $orderCustomer->getEmail();
$orderNumber = $order->getOrderNumber();
$orderAmount = $order->getAmountTotal();
$purchaseTime = date("ymdHis");
$this->sessionInterface->set('successURL', $successUrl);
try {
$this->logger->debug('Started in try block');
$redirectURL = $this->ExecutePayment($successUrl,$orderID, $orderNumber, $orderAmount, $purchaseTime, $customerEmail);
} catch (\Exception $e) {
throw new AsyncPaymentProcessException(
$transaction->getOrderTransaction()->getId(),
'An error occurred during the communication with external payment gateway' . PHP_EOL . $e->getMessage()
);
}
// Redirect to external gateway
return new RedirectResponse($redirectURL);
}
ExecutePayment() Function
public function ExecutePayment($orderID, $orderNumber, $totalAmount, $purchaseTime, $customerEmail): string
{
//signature creation edhe variable set
$b64sign = base64_encode($signature);
$ecgValues = [
'Version' => $Version,
'MerchantID' => $MerchantID,
'TerminalID' => $TerminalID,
'Currency' => $CurrencyID,
'locale' => "sq",
'TotalAmount' => $totalAmount,
'PurchaseTime' => $purchaseTime,
'PurchaseDesc' => "Pay order with ID: {$orderNr}.",
'Email' => $email,
'OrderID' => $orderNr,
'Delay' => $Delay,
'Signature' => $b64sign
];
try {
$html = "";
$html .= "<form id='redirectform' name='redirectpost' method='POST' action='https://xxxxxxxxxxxx/pay'>";
foreach ($ecgValues as $name => $value) $html .= "<input type='hidden' name='{$name}' value='{$value}'>";
$html .= "</form>";
$html .= "<script type='text/javascript'>document.getElementById('redirectform').submit(); </script>";
$response->setContent($html);
print $response;
} catch (Exception $e) {
$response->setCode($e->getCode() ?? 403);
$response->setBody($e->getMessage());
}
return $response;
}
This form is created based in the documentation of Payment Provider and it works as expected.
When the payment is selected in checkout and the Pay button is hit, the page redirects in the given action URL „https://xxxxxxxxxxxx/pay“. After I fill the fields (card number, CVV2 and date) with test numbers, the transaction is successfully completed and the page is redirected in the storefront controller provided (checkout/success).
From this point, I can’t call finalize() function from shopware.
I have added a button in success.html.twig which has the URL which redirects to homepage. But, when the site is redirected, even if the customer is logged, I think the session is destroyed and there is not any information saved from before payment process.
So, my questions are:
- How can I redirect from external payment gateway to checkout/finish?orderId=xxxx and execute the finalize() default shopware function.
or
- How can I redirect to homepage or checkout/finish?orderId=xxxx from storefront controller checkout/success without losing the session information (customer logged in).
Thank you in advance.