Skip to content

Commit

Permalink
PISHPS-352: Fix shipping for loggedin users (#854)
Browse files Browse the repository at this point in the history
* NTR: PISHPS-352: Fix shipping for loggedin users

* NTR: Cs fix

---------

Co-authored-by: Vitalij Mik <[email protected]>
  • Loading branch information
BlackScorp and Vitalij Mik authored Oct 2, 2024
1 parent 2dcb708 commit 60d790a
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);

namespace Kiener\MolliePayments\Components\ApplePayDirect\Services;

use Kiener\MolliePayments\Repository\Customer\CustomerRepositoryInterface;
use Kiener\MolliePayments\Repository\CustomerAddress\CustomerAddressRepositoryInterface;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\Uuid\Uuid;

/**
* We have to create a Fake Address in Case for Apple Pay Direct in order to load te correct shipping costs.
* The shipping costs are loaded based on rules, if a customer is already logged in and using apple pay direct, then the country from his current address is used for the rules.
* we have to add a temporary fake address to this customer in order to load correct shipping costs. afterwards we clear them
*/
class ApplePayShippingAddressFaker
{
private const ID_SUFFIX = 'applePayAddressId';
private CustomerRepositoryInterface $customerRepository;
private CustomerAddressRepositoryInterface $customerAddressRepository;

public function __construct(
CustomerRepositoryInterface $customerRepository,
CustomerAddressRepositoryInterface $customerAddressRepository
) {
$this->customerRepository = $customerRepository;
$this->customerAddressRepository = $customerAddressRepository;
}


public function createFakeShippingAddress(string $countryId, CustomerEntity $customerEntity, Context $context): string
{
$applePayAddressId = $this->generateAddressId($customerEntity);

$this->customerRepository->update([
[
'id' => $customerEntity->getId(),
'addresses' => [
[
'id' => $applePayAddressId,
'salutationId' => $customerEntity->getSalutationId(),
'countryId' => $countryId,
'firstName' => $customerEntity->getFirstName(),
'lastName' => $customerEntity->getLastName(),
'city' => 'not provided', //city is not necessary for rule builder
'street' => 'not provided' //apple pay event "onshippingcontactselected" does not prvide a street https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778009-onshippingcontactselected
]
]
]
], $context);

return $applePayAddressId;
}

public function deleteFakeShippingAddress(CustomerEntity $customerEntity, Context $context): void
{
$applePayAddressId = $this->generateAddressId($customerEntity);
$this->customerAddressRepository->delete([
[
'id' => $applePayAddressId
]
], $context);
}

private function generateAddressId(CustomerEntity $customerEntity): string
{
/** We cant use here Uuid::fromString because it does not exists in SW6.4 */
return Uuid::fromBytesToHex(md5($customerEntity->getId() . '-' . self::ID_SUFFIX, true));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ public function getShippingMethods(string $countryID, SalesChannelContext $conte

$availableShippingMethods = $this->shippingMethods->getActiveShippingMethods($context);

$this->cartService->clearFakeAddressIfExists($context);

foreach ($availableShippingMethods as $method) {
# temporary switch to our shipping method.
# we will then load the cart for this shipping method
Expand Down
34 changes: 34 additions & 0 deletions src/Repository/CustomerAddress/CustomerAddressRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);

namespace Kiener\MolliePayments\Repository\CustomerAddress;

use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;

class CustomerAddressRepository implements CustomerAddressRepositoryInterface
{
/**
* @var EntityRepository
*/
private $customerAddressRepository;

/**
* @param EntityRepository $customerAddressRepository
*/
public function __construct($customerAddressRepository)
{
$this->customerAddressRepository = $customerAddressRepository;
}

/**
* @param array<mixed> $ids
* @param Context $context
* @return EntityWrittenContainerEvent
*/
public function delete(array $ids, Context $context): EntityWrittenContainerEvent
{
return $this->customerAddressRepository->delete($ids, $context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);

namespace Kiener\MolliePayments\Repository\CustomerAddress;

use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;

interface CustomerAddressRepositoryInterface
{
/**
* @param array<mixed> $ids
* @param Context $context
* @return EntityWrittenContainerEvent
*/
public function delete(array $ids, Context $context): EntityWrittenContainerEvent;
}
5 changes: 5 additions & 0 deletions src/Resources/config/services/components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
<argument type="service" id="mollie_payments.logger"/>
</service>

<service id="Kiener\MolliePayments\Components\ApplePayDirect\Services\ApplePayShippingAddressFaker">
<argument type="service" id="Kiener\MolliePayments\Repository\Customer\CustomerRepository"/>
<argument type="service" id="Kiener\MolliePayments\Repository\CustomerAddress\CustomerAddressRepository"/>
</service>


</services>
</container>
4 changes: 4 additions & 0 deletions src/Resources/config/services/repositories.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
<argument type="service" id="state_machine_state.repository"/>
</service>

<service id="Kiener\MolliePayments\Repository\CustomerAddress\CustomerAddressRepository">
<argument type="service" id="customer_address.repository"/>
</service>



</services>
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<argument type="service" id="Shopware\Core\System\SalesChannel\SalesChannel\SalesChannelContextSwitcher"/>
<argument type="service" id="Shopware\Core\Checkout\Cart\LineItemFactoryHandler\ProductLineItemFactory"/>
<argument type="service" id="Kiener\MolliePayments\Compatibility\Gateway\CompatibilityGateway"/>
<argument type="service" id="Kiener\MolliePayments\Components\ApplePayDirect\Services\ApplePayShippingAddressFaker"/>
</service>

<service id="Kiener\MolliePayments\Service\Voucher\VoucherService" class="Kiener\MolliePayments\Service\Cart\Voucher\VoucherService">
Expand Down
33 changes: 29 additions & 4 deletions src/Service/CartService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

use Kiener\MolliePayments\Compatibility\Gateway\CompatibilityGateway;
use Kiener\MolliePayments\Compatibility\Gateway\CompatibilityGatewayInterface;
use Kiener\MolliePayments\Components\ApplePayDirect\Services\ApplePayShippingAddressFaker;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\LineItemFactoryHandler\ProductLineItemFactory;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService as SalesChannelCartService;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Framework\Validation\DataBag\DataBag;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\System\SalesChannel\SalesChannel\SalesChannelContextSwitcher;
Expand Down Expand Up @@ -34,19 +36,25 @@ class CartService implements CartServiceInterface
*/
private $compatibilityGateway;

/**
* @var ApplePayShippingAddressFaker
*/
private $shippingAddressFaker;


/**
* @param SalesChannelCartService $swCartService
* @param SalesChannelContextSwitcher $contextSwitcher
* @param ProductLineItemFactory $productItemFactory
* @param CompatibilityGateway $compatibilityGateway
*/
public function __construct(SalesChannelCartService $swCartService, SalesChannelContextSwitcher $contextSwitcher, ProductLineItemFactory $productItemFactory, CompatibilityGatewayInterface $compatibilityGateway)
public function __construct(SalesChannelCartService $swCartService, SalesChannelContextSwitcher $contextSwitcher, ProductLineItemFactory $productItemFactory, CompatibilityGatewayInterface $compatibilityGateway, ApplePayShippingAddressFaker $shippingAddressFaker)
{
$this->swCartService = $swCartService;
$this->contextSwitcher = $contextSwitcher;
$this->productItemFactory = $productItemFactory;
$this->compatibilityGateway = $compatibilityGateway;
$this->shippingAddressFaker = $shippingAddressFaker;
}


Expand Down Expand Up @@ -106,10 +114,17 @@ public function getShippingCosts(Cart $cart): float
public function updateCountry(SalesChannelContext $context, string $countryID): SalesChannelContext
{
$dataBag = new DataBag();

$dataBag->add([
$dataBagData = [
SalesChannelContextService::COUNTRY_ID => $countryID
]);
];
$customer = $context->getCustomer();

if ($customer instanceof CustomerEntity) {
$applePayAddressId = $this->shippingAddressFaker->createFakeShippingAddress($countryID, $customer, $context->getContext());
$dataBagData[SalesChannelContextService::SHIPPING_ADDRESS_ID] = $applePayAddressId;
}

$dataBag->add($dataBagData);

$this->contextSwitcher->update($dataBag, $context);

Expand Down Expand Up @@ -161,4 +176,14 @@ public function updatePaymentMethod(SalesChannelContext $context, string $paymen

return $this->compatibilityGateway->getSalesChannelContext($scID, $dID, $context->getToken());
}

public function clearFakeAddressIfExists(SalesChannelContext $context): void
{
$customer = $context->getCustomer();
if ($customer === null) {
return;
}

$this->shippingAddressFaker->deleteFakeShippingAddress($customer, $context->getContext());
}
}

0 comments on commit 60d790a

Please sign in to comment.