diff --git a/config.json b/config.json index 72bb36e..0562aa7 100755 --- a/config.json +++ b/config.json @@ -346,7 +346,7 @@ "required": false, "label": "Config.invoicesecuredb2cChannelIdLabel", "options": { - "defaultValue": "31HA07BC81895ACFE22C154CBC521922" + "defaultValue": "31HA07BC8129FBA7AF65934626B0F907" } }, "invoicesecuredb2c.minAmount": { diff --git a/resources/lib/invoiceSecuredB2CTransactionRequest.php b/resources/lib/invoiceSecuredB2CTransactionRequest.php new file mode 100755 index 0000000..aa18467 --- /dev/null +++ b/resources/lib/invoiceSecuredB2CTransactionRequest.php @@ -0,0 +1,64 @@ + + * + * @package heidelpay\plentymarkets-gateway\external-lib-callbacks + */ + +use Heidelpay\PhpPaymentApi\Request; + +/** @var array $requestParams */ +$requestParams = SdkRestApi::getParam('request'); +$transactionType = SdkRestApi::getParam('transactionType'); + +$paymentMethod = new \Heidelpay\PhpPaymentApi\PaymentMethods\InvoiceB2CSecuredPaymentMethod(); +$paymentMethod->setRequest(Request::fromPost($requestParams)); + +$responseArray = null; + +$refId = SdkRestApi::getParam('referenceId') ?: null; +$paymentFrameOrigin = $paymentMethod->getRequest()->getFrontend()->getPaymentFrameOrigin(); +$preventAsyncRedirect = $paymentMethod->getRequest()->getFrontend()->getPreventAsyncRedirect(); +$cssPath = $paymentMethod->getRequest()->getFrontend()->getCssPath(); + +try { + if (!is_callable([$paymentMethod, $transactionType])) { + throw new \Exception('Invalid transaction type for InvoiceB2CSecured payment method (' . $transactionType . ')!'); + } + + if ($refId !== null) { + $response = $paymentMethod->{$transactionType}( + $refId, + $paymentFrameOrigin, + $preventAsyncRedirect, + $cssPath + ); + } else { + $response = $paymentMethod->{$transactionType}($paymentFrameOrigin, $preventAsyncRedirect, $cssPath); + } +} catch (\Exception $e) { + $errorResponse = [ + 'exceptionCode' => $e->getCode(), + 'exceptionMsg' => $e->getMessage(), + 'exceptionTrace' => $e->getTraceAsString(), + ]; +} + +// return the responseArray, if an exception has been thrown. +// else, return an array containing response results. +$responseObj = $paymentMethod->getResponse(); +$responseArray = $responseObj->toArray(); +ksort($responseArray); +return $errorResponse ?? [ + 'response' => $responseArray, + 'isSuccess' => $responseObj->isSuccess(), + 'isPending' => $responseObj->isPending(), + 'isError' => $responseObj->isError(), +]; diff --git a/resources/lib/submitBasket.php b/resources/lib/submitBasket.php index d7344f0..b87568c 100755 --- a/resources/lib/submitBasket.php +++ b/resources/lib/submitBasket.php @@ -12,27 +12,82 @@ * @package heidelpay\plentymarkets-gateway\external-lib-callbacks */ +use Heidelpay\PhpBasketApi\Object\BasketItem; use Heidelpay\PhpBasketApi\Request as BasketApiRequest; +function normalizeValue($value) { + return (int)round(abs($value) * 100); +} + /** @var array $authData */ $authData = SdkRestApi::getParam('auth'); /** @var array $basketData */ $basketData = SdkRestApi::getParam('basket'); +/** @var array $basketItems */ +$basketItems = SdkRestApi::getParam('basketItems'); /** @var bool $sandmoxmode */ $sandboxmode = SdkRestApi::getParam('sandboxmode'); $basket = new \Heidelpay\PhpBasketApi\Object\Basket(); -$basket->setAmountTotalNet((int) $basketData['basketAmountNet'] * 100); -//$basket->setAmountTotalVat($basketData['??']); -$basket->setAmountTotalDiscount((int) $basketData['basketRebate'] * 100); - -foreach ($basketData['basketItems'] as $cartItem) { - $basketItem = new \Heidelpay\PhpBasketApi\Object\BasketItem(); - $basketItem->setAmountGross((int) $cartItem['basketAmount'] * 100); - $basketItem->setAmountNet((int) $cartItem['basketAmountNet'] * 100); - $basketItem->setAmountDiscount((int) $cartItem['rebate'] * 100); - $basketItem->setQuantity((int) $cartItem['quantity'] * 100); - $basketItem->setVat((int) $cartItem['vat'] * 100); +$basketAmount = $basketData['basketAmount']; +$basketAmountNet = $basketData['basketAmountNet']; +$basketAmountVat = $basketAmount - $basketAmountNet; +$basket->setAmountTotalNet(normalizeValue($basketAmountNet)) + ->setCurrencyCode($basketData['currency']) + ->setAmountTotalVat(normalizeValue($basketAmountVat)); +$goodsAndShipmentNet = 0; + +foreach ($basketItems as $item) { + $basketItem = new BasketItem(); + $quantity = $item['quantity']; + $amount = $item['price'] * $quantity; + $vat = $item['vat']; + $amountNet = $amount * 100 / (100 + $vat); + $amountVat = $amount - $amountNet; // $amountNet * $vat / 100; + $basketItem->setAmountGross(normalizeValue($amount)) + ->setAmountVat(normalizeValue($amountVat)) + ->setAmountNet(normalizeValue($amountNet)) + ->setAmountDiscount(normalizeValue($item['rebate'])) + ->setQuantity($quantity) + ->setVat($vat) + ->setAmountPerUnit(normalizeValue($item['price'])) + ->setBasketItemReferenceId($item['id']) + ->setTitle($item['title']) + ->setType('goods'); + $basket->addBasketItem($basketItem); + $goodsAndShipmentNet += $amountNet; +} + +// Add shipping position +$shipping = new BasketItem(); +$shippingAmount = $basketData['shippingAmount']; +$shippingNet = $basketData['shippingAmountNet']; +$shippingVat = $shippingAmount - $shippingNet; +$shipping->setAmountGross(normalizeValue($shippingAmount)) + ->setAmountNet(normalizeValue($shippingNet)) + ->setAmountVat(normalizeValue($shippingVat)) + ->setQuantity(1) + ->setAmountPerUnit(normalizeValue($shippingAmount)) + ->setBasketItemReferenceId('shipment') + ->setTitle('Shipment') + ->setType('shipment'); +$basket->addBasketItem($shipping); +$goodsAndShipmentNet += $shippingNet; + +// Add discount position +$discountAmount = $basketData['couponDiscount']; +if ($discountAmount !== 0) { + $discountItem = new BasketItem(); + $discountNet = $basketAmountNet - $goodsAndShipmentNet; + $discountItem->setAmountGross(normalizeValue($discountAmount)) + ->setAmountNet(normalizeValue($discountNet)) + ->setQuantity(1) + ->setAmountPerUnit(normalizeValue($discountAmount)) + ->setBasketItemReferenceId('discount') + ->setTitle('Discount') + ->setType('voucher'); + + $basket->addBasketItem($discountItem); } $request = new BasketApiRequest(); diff --git a/resources/views/invoiceSecuredB2CForm.twig b/resources/views/invoiceSecuredB2CForm.twig index d61e86c..f54d577 100755 --- a/resources/views/invoiceSecuredB2CForm.twig +++ b/resources/views/invoiceSecuredB2CForm.twig @@ -8,10 +8,10 @@
- + + +
@@ -23,44 +23,44 @@
- + + {% for day in 1..31 %} + {% set day = '%02d'|format(day) %} + + {% endfor %}
- + + {% for month in 1..12 %} + {% set month = '%02d'|format(month) %} + + {% endfor %}
- + {% set minYear = "now -80 years"|date("Y") %} {% set maxYear = "now -18 years"|date("Y") %} - + {% for year in maxYear..minYear %} + + {% endfor %}
diff --git a/src/Controllers/ResponseController.php b/src/Controllers/ResponseController.php index 1237c65..edf0ce7 100755 --- a/src/Controllers/ResponseController.php +++ b/src/Controllers/ResponseController.php @@ -4,6 +4,8 @@ use Heidelpay\Constants\Routes; use Heidelpay\Exceptions\SecurityHashInvalidException; +use Heidelpay\Helper\PaymentHelper; +use Heidelpay\Methods\PaymentMethodContract; use Heidelpay\Models\Transaction; use Heidelpay\Services\Database\TransactionService; use Heidelpay\Services\NotificationServiceContract; @@ -14,6 +16,7 @@ use Plenty\Plugin\Controller; use Plenty\Plugin\Http\Request; use Plenty\Plugin\Http\Response; +use Symfony\Component\HttpFoundation\Response as BaseResponse; /** * Processes the transaction/payment responses coming from the heidelpay payment system. @@ -70,6 +73,7 @@ public function __construct( $this->urlService = $urlService; } + // /** * Creates a transaction object and returns bool to indicate success. * @@ -106,6 +110,48 @@ private function createAndHandleTransaction($response, $responseObject): bool return true; } + + + /** + * Returns the salutation from the post request. + * + * @return string + * @throws \RuntimeException + */ + private function getSalutation(): string + { + if ($this->request->exists('customer_salutation')) { + return $this->request->get('customer_salutation'); + } + + throw new \RuntimeException('Salutation not set!'); + } + + /** + * Returns the date of birth from the request. + * + * @return string + * @throws \RuntimeException + */ + private function getDateOfBirth(): string + { + if ($this->request->exists('customer_dob_day') && + $this->request->exists('customer_dob_month') && + $this->request->exists('customer_dob_year')) { + return implode( + '-', + [ + $this->request->get('customer_dob_year'), + $this->request->get('customer_dob_month'), + $this->request->get('customer_dob_day') + ] + ); + } + + throw new \RuntimeException('Date of birth not set!'); + } + // + // /** * Process the incoming POST response and return the redirect url depending on the response result. @@ -178,9 +224,9 @@ public function processPush(): Response * the heidelpay API redirects to the processAsyncResponse url using GET instead of POST. * This method is for handling this behaviour. * - * @return \Symfony\Component\HttpFoundation\Response + * @return BaseResponse */ - public function emergencyRedirect(): \Symfony\Component\HttpFoundation\Response + public function emergencyRedirect(): BaseResponse { $this->notification->warning('response.warningResponseCalledInInvalidContext', __METHOD__); return $this->response->redirectTo('checkout'); @@ -190,13 +236,40 @@ public function emergencyRedirect(): \Symfony\Component\HttpFoundation\Response * Handles form requests which do not need any further action by the client. * * @param BasketRepositoryContract $basketRepo - * @return \Symfony\Component\HttpFoundation\Response + * @param PaymentHelper $paymentHelper + * @return BaseResponse + * @throws \RuntimeException */ - public function handleSyncRequest(BasketRepositoryContract $basketRepo): \Symfony\Component\HttpFoundation\Response - { + public function handleSyncRequest( + BasketRepositoryContract $basketRepo, + PaymentHelper $paymentHelper + ): BaseResponse { $basket = $basketRepo->load(); - $this->notification->success('payment.infoPaymentSuccessful', __METHOD__, ['basket' => $basket]); + $mopId = $basket->methodOfPaymentId; + $paymentMethod = $paymentHelper->mapMopToPaymentMethod($mopId); + $methodInstance = $paymentHelper->getPaymentMethodInstanceByMopId($mopId); + if (!$methodInstance instanceof PaymentMethodContract) { + $this->notification->error('payment.errorDuringPaymentExecution', __METHOD__); + return $this->response->redirectTo('checkout'); + } + + $response = $this->paymentService->sendPaymentRequest( + $basket, + $paymentMethod, + $methodInstance->getTransactionType(), + $mopId, + ['birthday' => $this->getDateOfBirth(), 'salutation' => $this->getSalutation()] + ); + + if ($response['isError'] === true) { + $responseObj = $response['response']; + $errorMsg = ($responseObj['PROCESSING.REASON'] ?? '') . ': ' . ($responseObj['PROCESSING.RETURN'] ?? ''); + $this->notification->error('payment.errorDuringPaymentExecution', __METHOD__, ['Message' => $errorMsg]); + return $this->response->redirectTo('checkout'); + } + + $this->notification->success('payment.infoPaymentSuccessful', __METHOD__); return $this->response->redirectTo('place-order'); } // diff --git a/src/Methods/AbstractMethod.php b/src/Methods/AbstractMethod.php index 30d351f..0c8bd72 100755 --- a/src/Methods/AbstractMethod.php +++ b/src/Methods/AbstractMethod.php @@ -31,6 +31,8 @@ abstract class AbstractMethod extends PaymentMethodService implements PaymentMet const RETURN_TYPE = GetPaymentMethodContent::RETURN_TYPE_REDIRECT_URL; const INITIALIZE_PAYMENT = true; const FORM_TEMPLATE = ''; + const NEEDS_CUSTOMER_INPUT = true; + const NEEDS_BASKET = false; /** * @var PaymentHelper $helper @@ -244,4 +246,23 @@ public function getFormTemplate(): string { return static::FORM_TEMPLATE; } + + /** + * Returns true if the customer has to be redirected to enter additional information (e.g. 3D-secure, sofort, etc.). + * This determines whether a synchronous or asynchronous request is performed. + * + * @return bool + */ + public function needsCustomerInput(): bool + { + return static::NEEDS_CUSTOMER_INPUT; + } + + /** + * {@inheritDoc} + */ + public function needsBasket(): bool + { + return static::NEEDS_BASKET; + } } diff --git a/src/Methods/InvoiceSecuredB2C.php b/src/Methods/InvoiceSecuredB2C.php index 36d5c88..6e932e8 100755 --- a/src/Methods/InvoiceSecuredB2C.php +++ b/src/Methods/InvoiceSecuredB2C.php @@ -1,6 +1,7 @@ get(Routes::RESPONSE_URL, 'Heidelpay\Controllers\ResponseController@emergencyRedirect'); $router->post(Routes::RESPONSE_URL, 'Heidelpay\Controllers\ResponseController@processAsyncResponse'); $router->post(Routes::PUSH_NOTIFICATION_URL, 'Heidelpay\Controllers\ResponseController@processPush'); - $router->get(Routes::HANDLE_FORM_URL, 'Heidelpay\Controllers\ResponseController@emergencyRedirect'); $router->post(Routes::HANDLE_FORM_URL, 'Heidelpay\Controllers\ResponseController@handleSyncRequest'); // redirects in success or cancellation/failure cases diff --git a/src/Services/BasketService.php b/src/Services/BasketService.php index 52e34f6..88ee76d 100755 --- a/src/Services/BasketService.php +++ b/src/Services/BasketService.php @@ -3,7 +3,11 @@ namespace Heidelpay\Services; use Heidelpay\Configs\MainConfigContract; +use Plenty\Modules\Authorization\Services\AuthHelper; use Plenty\Modules\Basket\Models\Basket; +use Plenty\Modules\Basket\Models\BasketItem; +use Plenty\Modules\Item\Item\Contracts\ItemRepositoryContract; +use Plenty\Modules\Item\Item\Models\Item; /** * Provides connection to heidelpay basketApi. @@ -27,18 +31,32 @@ class BasketService * @var MainConfigContract */ private $config; + /** + * @var AuthHelper + */ + private $authHelper; + /** + * @var ItemRepositoryContract + */ + private $itemRepo; /** * BasketService constructor. * @param LibService $libraryService * @param MainConfigContract $config + * @param ItemRepositoryContract $itemRepo + * @param AuthHelper $authHelper */ public function __construct( LibService $libraryService, - MainConfigContract $config + MainConfigContract $config, + ItemRepositoryContract $itemRepo, + AuthHelper $authHelper ) { $this->libService = $libraryService; $this->config = $config; + $this->authHelper = $authHelper; + $this->itemRepo = $itemRepo; } /** @@ -58,8 +76,23 @@ public function requestBasketId(Basket $basket, array $authData): string 'senderId' => $authData['SECURITY_SENDER'], ]; $params['basket'] = $basket->toArray(); - $params['sandboxmode'] = $this->config->isInSandboxMode(); + $items = []; + foreach ($basket->basketItems as $basketItem) { + /** @var BasketItem $basketItem */ + /** @var Item $item */ + $item = $this->authHelper->processUnguarded( + function () use ($basketItem) { + return $this->itemRepo->show($basketItem->itemId); + } + ); + $itemArray = $basketItem->toArray(); + $itemArray['title'] = $item->texts[0]->name1; + $items[] = $itemArray; + } + + $params['basketItems'] = $items; + $params['sandboxmode'] = $this->config->isInSandboxMode(); $response = $this->libService->submitBasket($params); return $response['basketId']; } diff --git a/src/Services/PaymentService.php b/src/Services/PaymentService.php index dc36cc8..5a38ebe 100755 --- a/src/Services/PaymentService.php +++ b/src/Services/PaymentService.php @@ -5,7 +5,6 @@ use Heidelpay\Configs\MethodConfigContract; use Heidelpay\Constants\Plugin; use Heidelpay\Constants\Routes; -use Heidelpay\Constants\Salutation; use Heidelpay\Constants\SessionKeys; use Heidelpay\Constants\TransactionStatus; use Heidelpay\Constants\TransactionType; @@ -21,6 +20,7 @@ use Heidelpay\Traits\Translator; use Plenty\Modules\Account\Address\Contracts\AddressRepositoryContract; use Plenty\Modules\Account\Address\Models\Address; +use Plenty\Modules\Account\Contact\Contracts\ContactRepositoryContract; use Plenty\Modules\Basket\Contracts\BasketRepositoryContract; use Plenty\Modules\Basket\Models\Basket; use Plenty\Modules\Frontend\Session\Storage\Contracts\FrontendSessionStorageFactoryContract; @@ -113,6 +113,10 @@ class PaymentService * @var BasketRepositoryContract */ private $basketRepository; + /** + * @var ContactRepositoryContract + */ + private $contactRepo; /** * PaymentService constructor. @@ -131,6 +135,7 @@ class PaymentService * @param OrderRepositoryContract $orderRepo * @param UrlServiceContract $urlService * @param BasketRepositoryContract $basketRepository + * @param ContactRepositoryContract $contactRepo */ public function __construct( AddressRepositoryContract $addressRepository, @@ -146,7 +151,8 @@ public function __construct( OrderTxnIdRelationRepositoryContract $orderTxnIdRepo, OrderRepositoryContract $orderRepo, UrlServiceContract $urlService, - BasketRepositoryContract $basketRepository + BasketRepositoryContract $basketRepository, + ContactRepositoryContract $contactRepo ) { $this->addressRepository = $addressRepository; $this->countryRepository = $countryRepository; @@ -162,6 +168,7 @@ public function __construct( $this->orderRepo = $orderRepo; $this->urlService = $urlService; $this->basketRepository = $basketRepository; + $this->contactRepo = $contactRepo; } /** @@ -224,7 +231,7 @@ public function executePayment(string $paymentMethod, ExecutePayment $event): ar * @param string $paymentMethod * @param string $transactionType * @param int $mopId - * @param array $parameters + * @param array $additionalParams * * @return array * @throws \RuntimeException @@ -234,17 +241,16 @@ public function sendPaymentRequest( string $paymentMethod, string $transactionType, int $mopId, - array $parameters = [] + array $additionalParams = [] ): array { $txnId = $this->createNewTxnId($basket); $this->createOrUpdateRelation($txnId, $mopId); - $this->prepareRequest($basket, $paymentMethod, $mopId, $txnId); + $this->prepareRequest($basket, $paymentMethod, $mopId, $txnId, $additionalParams); $result = $this->libService->sendTransactionRequest($paymentMethod, [ 'request' => $this->heidelpayRequest, - 'transactionType' => $transactionType, - 'parameters' => $parameters + 'transactionType' => $transactionType ]); return $result; @@ -301,9 +307,22 @@ public function getPaymentMethodContent( } } + $basket = $this->basketRepository->load(); + $customerId = $basket->customerId; + + $contact = $this->contactRepo->findContactById($customerId); + $birthday = explode('-', substr($contact->birthdayAt, 0, 10)); + if ($type === GetPaymentMethodContent::RETURN_TYPE_HTML) { // $value should contain the payment frame url (also form url) - $value = $this->renderPaymentForm($methodInstance->getFormTemplate(), ['submit_action' => $value]); + $parameters = [ + 'submit_action' => $value, + 'customer_dob_day' => $birthday[2] ?? '', + 'customer_dob_month' => $birthday[1] ?? '', + 'customer_dob_year' => $birthday[0] ?? '', + 'customer_gender' => $contact->gender + ]; + $value = $this->renderPaymentForm($methodInstance->getFormTemplate(), $parameters); } return [$type, $value]; @@ -314,9 +333,15 @@ public function getPaymentMethodContent( * @param string $paymentMethod * @param int $mopId * @param string $transactionId + * @param array $additionalParams * @throws \RuntimeException */ - private function prepareRequest(Basket $basket, string $paymentMethod, int $mopId, string $transactionId) + private function prepareRequest( + Basket $basket, + string $paymentMethod, + int $mopId, + string $transactionId, + array $additionalParams = []) { $basketArray = $basket->toArray(); @@ -326,26 +351,30 @@ private function prepareRequest(Basket $basket, string $paymentMethod, int $mopI /** @var SecretService $secretService */ $secretService = pluginApp(SecretService::class); + /** @var PaymentMethodContract $methodInstance */ + $methodInstance = $this->paymentHelper->getPaymentMethodInstance($paymentMethod); + // set authentication data $heidelpayAuth = $this->paymentHelper->getHeidelpayAuthenticationConfig($paymentMethod); $this->heidelpayRequest = array_merge($this->heidelpayRequest, $heidelpayAuth); // set customer personal information & address data - $addresses = $this->getCustomerAddressData($basket); + $addresses = $this->getCustomerAddressData($basket); + $billingAddress = $addresses['billing']; $this->heidelpayRequest['IDENTIFICATION_SHOPPERID'] = $basketArray['customerId']; - $this->heidelpayRequest['NAME_GIVEN'] = $addresses['billing']->firstName; - $this->heidelpayRequest['NAME_FAMILY'] = $addresses['billing']->lastName; - $this->heidelpayRequest['CONTACT_EMAIL'] = $addresses['billing']->email; - $this->heidelpayRequest['ADDRESS_STREET'] = $this->getFullStreetAndHouseNumber($addresses['billing']); - $this->heidelpayRequest['ADDRESS_ZIP'] = $addresses['billing']->postalCode; - $this->heidelpayRequest['ADDRESS_CITY'] = $addresses['billing']->town; - $this->heidelpayRequest['ADDRESS_COUNTRY'] = $this->countryRepository->findIsoCode( - $addresses['billing']->countryId, + $this->heidelpayRequest['NAME_GIVEN'] = $billingAddress->firstName; + $this->heidelpayRequest['NAME_FAMILY'] = $billingAddress->lastName; + $this->heidelpayRequest['CONTACT_EMAIL'] = $billingAddress->email; + $this->heidelpayRequest['ADDRESS_STREET'] = $this->getFullStreetAndHouseNumber($billingAddress); + $this->heidelpayRequest['ADDRESS_ZIP'] = $billingAddress->postalCode; + $this->heidelpayRequest['ADDRESS_CITY'] = $billingAddress->town; + $this->heidelpayRequest['ADDRESS_COUNTRY'] = $this->countryRepository->findIsoCode( + $billingAddress->countryId, 'isoCode2' ); - if ($addresses['billing']->companyName !== null) { - $this->heidelpayRequest['NAME_COMPANY'] = $addresses['billing']->companyName; + if ($billingAddress->companyName !== null) { + $this->heidelpayRequest['NAME_COMPANY'] = $billingAddress->companyName; } $this->heidelpayRequest['IDENTIFICATION_TRANSACTIONID'] = $transactionId; @@ -361,7 +390,7 @@ private function prepareRequest(Basket $basket, string $paymentMethod, int $mopI $this->heidelpayRequest['PRESENTATION_AMOUNT'] = $basketArray['basketAmount']; $this->heidelpayRequest['PRESENTATION_CURRENCY'] = $basketArray['currency']; - $this->heidelpayRequest['FRONTEND_ENABLED'] = 'TRUE'; + $this->heidelpayRequest['FRONTEND_ENABLED'] = $methodInstance->needsCustomerInput() ? 'TRUE' : 'FALSE'; $this->heidelpayRequest['FRONTEND_LANGUAGE'] = $this->sessionStorageFactory->getLocaleSettings()->language; $this->heidelpayRequest['FRONTEND_RESPONSE_URL'] = $this->urlService->generateURL(Routes::RESPONSE_URL); @@ -372,12 +401,15 @@ private function prepareRequest(Basket $basket, string $paymentMethod, int $mopI $this->heidelpayRequest['FRONTEND_PREVENT_ASYNC_REDIRECT'] = 'false'; } - if (false) { - $this->heidelpayRequest['NAME_SALUTATION'] = $addresses['billing']->gender === 'male' - ? Salutation::MR - : Salutation::MRS; + if (isset($additionalParams['birthday'])) { + $this->heidelpayRequest['NAME_BIRTHDATE'] = $additionalParams['birthday']; + } + + if (isset($additionalParams['salutation'])) { + $this->heidelpayRequest['NAME_SALUTATION'] = $additionalParams['salutation']; + } - $this->heidelpayRequest['NAME_BIRTHDATE'] = $addresses['billing']->birthday; + if ($methodInstance->needsBasket()) { $this->heidelpayRequest['BASKET_ID'] = $basketService->requestBasketId($basket, $heidelpayAuth); } @@ -397,10 +429,9 @@ private function prepareRequest(Basket $basket, string $paymentMethod, int $mopI } // general - $methodInstance = $this->paymentHelper->getPaymentMethodInstance($paymentMethod); - if (null !== $methodInstance) { - $this->heidelpayRequest['FRONTEND_CSS_PATH'] = $this->methodConfig->getIFrameCssPath($methodInstance); - } + $this->heidelpayRequest['FRONTEND_CSS_PATH'] = $this->methodConfig->getIFrameCssPath($methodInstance); + + ksort($this->heidelpayRequest); } //