<?php declare(strict_types=1);
namespace Samson\Subscriber;
/***
*
* This file is part of the "SAMSON Shop" project.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021
*
***/
use Exception;
use Samson\CustomFieldSet\Constants\CustomerCustomFieldConstants;
use Samson\Defaults;
use Samson\Event\CustomDataMappingEvent;
use Samson\Event\Sap\SapCustomerAddressSynchronizationEvent;
use Samson\Event\Sap\SapCustomerRegistrationErrorEvent;
use Samson\Exception\SapApiRequestException;
use Samson\Service\PersistentCartService;
use Samson\Api\Soap\Service\SoapCustomerService;
use Sentry\State\Scope;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Checkout\Customer\Event\CustomerDoubleOptInRegistrationEvent;
use Shopware\Core\Checkout\Customer\Event\CustomerLoginEvent;
use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use function Sentry\captureException;
use function Sentry\withScope;
/**
* Class RegisterSubscriber
* @package Samson\Subscriber
* @author Christian Schmitz <christian.schmitz@dkd.de>
*/
class RegisterSubscriber implements EventSubscriberInterface
{
const ERROR_CUSTOMER_CREATION_IN_SAP = 'Error while creating a customer in SAP';
private PersistentCartService $persistentCartService;
private EntityRepositoryInterface $customerRepository;
private SystemConfigService $systemConfigService;
private SoapCustomerService $soapCustomerService;
private EventDispatcherInterface $eventDispatcher;
public function __construct(
PersistentCartService $persistentCartService,
EntityRepositoryInterface $customerRepository,
SystemConfigService $systemConfigService,
SoapCustomerService $soapCustomerService,
EventDispatcherInterface $eventDispatcher
)
{
$this->persistentCartService = $persistentCartService;
$this->customerRepository = $customerRepository;
$this->systemConfigService = $systemConfigService;
$this->soapCustomerService = $soapCustomerService;
$this->eventDispatcher = $eventDispatcher;
}
public static function getSubscribedEvents(): array
{
return [
CustomerLoginEvent::class => 'onCustomerLoginEvent',
CustomerRegisterEvent::class => 'onCustomerRegisterEvent',
CustomerEvents::MAPPING_REGISTER_CUSTOMER => 'onMappingRegisterCustomerEvent',
];
}
public function onCustomerLoginEvent(CustomerLoginEvent $event): void
{
if (!empty($event->getCustomer())) {
$this->persistentCartService->loadCart(
$event->getCustomer(),
$event->getContext(),
$event->getSalesChannelContext(),
$event->getContextToken()
);
}
}
/**
* @throws Exception
*/
public function onCustomerRegisterEvent(CustomerRegisterEvent $event): void
{
$salesChannelContext = $event->getSalesChannelContext();
if (!$this->systemConfigService->get(Defaults::SAP_ACTIVATION_KEY, $salesChannelContext->getSalesChannelId())) {
return;
}
if (!$this->systemConfigService->get(Defaults::SAP_CUSTOMER_REGISTRATION_KEY, $salesChannelContext->getSalesChannelId())) {
return;
}
$customer = $event->getCustomer();
$context = $event->getContext();
if (isset($customer->getCustomFields()[CustomerCustomFieldConstants::CUSTOM_FIELD_IS_SUB_ACCOUNT])
&& $customer->getCustomFields()[CustomerCustomFieldConstants::CUSTOM_FIELD_IS_SUB_ACCOUNT]) {
return;
}
try {
$customerExists = $this->soapCustomerService->checkIfCustomerExistsInSap($customer, $context);
if ($customerExists) {
$customerInfo = $this->soapCustomerService->synchronizeCustomerDataWithSap($customer, $context);
if (!empty($customerInfo) && !empty($customerInfo['address'])) {
$this->eventDispatcher->dispatch(
new SapCustomerAddressSynchronizationEvent($customerInfo['address'],
$customerInfo['customerNumber'],
$salesChannelContext->getSalesChannelId(),
$context),
SapCustomerRegistrationErrorEvent::EVENT_NAME);
}
} else {
$createCustomer = $this->soapCustomerService->createCustomerInSap($customer, $context);
if (!$createCustomer) {
$this->setCustomerInactiveIfErrorOccurs($customer, $context);
$this->eventDispatcher->dispatch(
new SapCustomerRegistrationErrorEvent(self::ERROR_CUSTOMER_CREATION_IN_SAP,
$salesChannelContext->getSalesChannelId(),
$context),
SapCustomerRegistrationErrorEvent::EVENT_NAME);
}
}
} catch (Exception $e) {
$this->setCustomerInactiveIfErrorOccurs($customer, $context);
$errorMessage = $e->getMessage() . ': ' . PHP_EOL;
if (isset($e->detail)) {
$faultDetails = $e->detail->MT_FAULT_MSG->standard->faultDetail;
foreach ($faultDetails as $faultDetail) {
$errorMessage = $errorMessage . $faultDetail->text . PHP_EOL;
}
}
$this->eventDispatcher->dispatch(
new SapCustomerRegistrationErrorEvent($errorMessage,
$salesChannelContext->getSalesChannelId(),
$context),
SapCustomerRegistrationErrorEvent::EVENT_NAME);
withScope(function (Scope $scope) use ($e, $errorMessage): void {
$scope->setContext('RegisterCustomerEventException',
[
'errorMessage' => $errorMessage
]);
captureException($e);
});
throw new SapApiRequestException($errorMessage);
}
}
public function onMappingRegisterCustomerEvent(CustomDataMappingEvent $event): void
{
if (!$this->systemConfigService->get(Defaults::SAP_ACTIVATION_KEY, $event->getSalesChannelContext()->getSalesChannelId())) {
return;
}
$data = $event->getInput();
$customer = $event->getOutput();
$hasCustomCustomerNumber = $data->has('customerNumber') && !empty($data->get('customerNumber'));
$customer['customerNumber'] = $hasCustomCustomerNumber ? $data->get('customerNumber') : Defaults::CUSTOMER_NUMBER_WILDCARD;
$event->setOutput($customer);
}
private function setCustomerInactiveIfErrorOccurs(CustomerEntity $customerEntity, Context $context): void
{
$this->customerRepository->update([['id' => $customerEntity->getId(), 'active' => false]], $context);
}
}