Skip to content

Commit

Permalink
Merge pull request #15 from Setono/fix-address-validation-during-chec…
Browse files Browse the repository at this point in the history
…kout

Added: NL/DE address validation during checkout/address creation/update
  • Loading branch information
igormukhingmailcom authored Jan 31, 2020
2 parents 6270f85 + 8256a43 commit 7684f8c
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 10 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ imports:
- { resource: "@SetonoSyliusQuickpayPlugin/Resources/config/app/fixtures.yaml" }
````
### 5: Add validator constraint
Create `config/validator/Address.xml`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Addressing\Model\Address">
<constraint name="Setono\SyliusQuickpayPlugin\Validator\Constraints\AddressStreetEligibility">
<option name="message">setono_sylius_quickpay.address.street_eligibility</option>
<option name="groups">
<value>sylius_shipping_address_update</value>
<value>sylius_checkout_complete</value>
<value>sylius</value>
</option>
</constraint>
</class>
</constraint-mapping>
```

Like it [configured](tests/Application/config/validator/Address.xml) at example application.

## Configuration

Create a new Payment method of the type *Quickpay* and fill out the required form fields.
Expand Down
37 changes: 32 additions & 5 deletions src/Action/ConvertPaymentAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\Intl\Countries;
use VIISON\AddressSplitter\AddressSplitter;
use VIISON\AddressSplitter\Exceptions\SplittingException;
use Webmozart\Assert\Assert;

/**
Expand Down Expand Up @@ -107,17 +108,43 @@ protected function convertAddress(AddressInterface $address, CustomerInterface $
$street = $address->getStreet();
Assert::notNull($street);

$splittedStreet = AddressSplitter::splitAddress($street);

$details = [];
switch (mb_strtoupper($countryCode)) {
case 'DE':
try {
$splittedStreet = AddressSplitter::splitAddress($street);

$details['street'] = $splittedStreet['streetName'];
$details['house_number'] = $splittedStreet['houseNumber'];
} catch (SplittingException $e) {
$details['street'] = $street;
$details['house_number'] = '';
}

break;
case 'NL':
try {
$splittedStreet = AddressSplitter::splitAddress($street);

$details['street'] = $splittedStreet['streetName'];
$details['house_number'] = $splittedStreet['houseNumberParts']['base'];
$details['house_extension'] = $splittedStreet['houseNumberParts']['extension'];
} catch (SplittingException $e) {
$details['street'] = $street;
$details['house_number'] = '';
$details['house_extension'] = '';
}

break;
default:
$details['street'] = $street;
}

$details['name'] = sprintf(
'%s %s',
$address->getFirstName(),
$address->getLastName()
);
$details['street'] = $splittedStreet['streetName'];
$details['house_number'] = $splittedStreet['houseNumberParts']['base'];
$details['house_extension'] = $splittedStreet['houseNumberParts']['extension'];
$details['city'] = $address->getCity();
$details['zip_code'] = $address->getPostcode();
$details['region'] = $address->getProvinceName() ?? $address->getProvinceCode();
Expand Down
49 changes: 49 additions & 0 deletions src/Checker/StreetEligibilityChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusQuickpayPlugin\Checker;

use Sylius\Component\Addressing\Model\AddressInterface;
use VIISON\AddressSplitter\AddressSplitter;
use VIISON\AddressSplitter\Exceptions\SplittingException;
use Webmozart\Assert\Assert;

class StreetEligibilityChecker implements StreetEligibilityCheckerInterface
{
public function isEligible(AddressInterface $address): bool
{
$countryCode = $address->getCountryCode();
Assert::notNull($countryCode);

$street = $address->getStreet();
if (null === $street) {
return false;
}

try {
switch (mb_strtoupper($countryCode)) {
case 'DE':
$splittedStreet = AddressSplitter::splitAddress($street);
if ('' === $splittedStreet['houseNumber']) {
return false;
}

break;
case 'NL':
$splittedStreet = AddressSplitter::splitAddress($street);
if ('' === $splittedStreet['houseNumberParts']['base']) {
return false;
}

if ('' === $splittedStreet['houseNumberParts']['extension']) {
return false;
}
}
} catch (SplittingException $e) {
return false;
}

return true;
}
}
12 changes: 12 additions & 0 deletions src/Checker/StreetEligibilityCheckerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusQuickpayPlugin\Checker;

use Sylius\Component\Addressing\Model\AddressInterface;

interface StreetEligibilityCheckerInterface
{
public function isEligible(AddressInterface $address): bool;
}
8 changes: 4 additions & 4 deletions src/Fixture/KlarnaTestShopUserFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ protected function getKlarnaTestDataByCountry(string $countryCode, array $option
'city' => 'Hausmannstätten',
'postcode' => $options['approved'] ? '8071' : '8070',
'gender' => $options['approved'] ? CustomerInterface::MALE_GENDER : CustomerInterface::FEMALE_GENDER,
'birthday' => $options['approved'] ? '1960-04-14' : '1980-04-14',
'birthday' => $options['approved'] ? '1960-04-14 00:00:00' : '1980-04-14 00:00:00',
],
'FI' => [
'phone_number' => '0401234567',
Expand All @@ -149,7 +149,7 @@ protected function getKlarnaTestDataByCountry(string $countryCode, array $option
'city' => 'Neuss',
'postcode' => '41460',
'gender' => CustomerInterface::MALE_GENDER,
'birthday' => '1960-07-07',
'birthday' => '1960-07-07 00:00:00',
],
'NO' => [
'phone_number' => '40 123 456',
Expand All @@ -163,7 +163,7 @@ protected function getKlarnaTestDataByCountry(string $countryCode, array $option
'city' => 'Gravenhage',
'postcode' => '2521VA',
'gender' => CustomerInterface::MALE_GENDER,
'birthday' => '1960-07-10',
'birthday' => '1960-07-10 00:00:00',
],
'CH' => [
'first_name' => $options['approved'] ? $this->faker->firstName : 'test',
Expand All @@ -173,7 +173,7 @@ protected function getKlarnaTestDataByCountry(string $countryCode, array $option
'city' => 'Zürich',
'postcode' => '8001',
'gender' => CustomerInterface::MALE_GENDER,
'birthday' => '1960-01-01',
'birthday' => '1960-01-01 00:00:00',
],
];

Expand Down
50 changes: 49 additions & 1 deletion src/Resources/config/app/fixtures.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ sylius_fixtures:
default:
fixtures:

geographical:
options:
countries:
- 'US'
- 'DK'
- 'NL'
zones:
EU:
name: "EU"
scope: "all"
countries:
- 'DK'
- 'NL'
currency:
options:
currencies:
Expand Down Expand Up @@ -30,12 +43,28 @@ sylius_fixtures:
- "DKK"
enabled: true
hostname: "localhost"
nl_web_store:
name: "NL Web Store"
code: 'NL_WEB'
locales:
- "%locale%"
currencies:
- "EUR"
enabled: true
hostname: "localhost"

setono_quickpay_klarna_test_shop_user:
setono_quickpay_klarna_test_shop_user_dk:
name: setono_quickpay_klarna_test_shop_user
options:
amount: 10
country: DK

setono_quickpay_klarna_test_shop_user_nl:
name: setono_quickpay_klarna_test_shop_user
options:
amount: 10
country: NL

# Temporary fix for https://github.com/Sylius/Sylius/issues/10719
# @todo Remove this lines once issue will be fixed
order:
Expand Down Expand Up @@ -72,6 +101,7 @@ sylius_fixtures:
- 'FASHION_WEB'
- 'EU_WEB'
- 'DK_WEB'
- 'NL_WEB'
enabled: true
quickpay_klarna:
code: 'quickpay_klarna'
Expand All @@ -97,6 +127,7 @@ sylius_fixtures:
use_authorize: true
channels:
- 'DK_WEB'
- 'NL_WEB'
enabled: true

shipping_method:
Expand All @@ -105,7 +136,24 @@ sylius_fixtures:
eu_courier:
code: 'eu_courier'
name: 'EU courier'
zone: 'EU'
enabled: true
channels:
- 'EU_WEB'
- 'DK_WEB'
- 'NL_WEB'

cap_product_nl:
name: product
options:
custom:
- name: 'Winter cap'
tax_category: 'other'
channels:
- 'NL_WEB'
main_taxon: 'caps_with_pompons'
taxons:
- 'caps'
- 'caps_with_pompons'
images:
- { path: '@SyliusCoreBundle/Resources/fixtures/caps/cap_01.jpg', type: 'main' }
14 changes: 14 additions & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@
alias="setono_sylius_quickpay.quickpay.convert_payment" />
</service>

<!-- Checker -->
<service id="setono_sylius_quickpay.street_eligibility_checker"
class="Setono\SyliusQuickpayPlugin\Checker\StreetEligibilityChecker">
</service>

<!-- Validator -->
<service id="setono_sylius_quickpay.validator.eligible_street"
class="Setono\SyliusQuickpayPlugin\Validator\AddressStreetEligibilityValidator">
<argument type="service" id="setono_sylius_quickpay.street_eligibility_checker" />

<tag name="validator.constraint_validator"
alias="setono_sylius_quickpay_address_street_eligibility_validator" />
</service>

<!-- State machine -->
<service id="setono_sylius_quickpay.state_machine_resolver"
class="Setono\SyliusQuickpayPlugin\StateMachine\Resolver"
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/translations/validators.da.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ setono_sylius_quickpay:
not_blank: Aftale id er påkrævet.
order_prefix:
max_length: Bør ikke være længere end 11 tegn.
address:
street_eligibility: Gaden skal indeholde husnummer (og udvidelse af husnummer for NL)
2 changes: 2 additions & 0 deletions src/Resources/translations/validators.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ setono_sylius_quickpay:
not_blank: Agreement id is required.
order_prefix:
max_length: Shouldn't be more than 11 chars length.
address:
street_eligibility: Street should contain house number (and extension for NL)
37 changes: 37 additions & 0 deletions src/Validator/AddressStreetEligibilityValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusQuickpayPlugin\Validator;

use Setono\SyliusQuickpayPlugin\Checker\StreetEligibilityCheckerInterface;
use Setono\SyliusQuickpayPlugin\Validator\Constraints\AddressStreetEligibility;
use Sylius\Component\Addressing\Model\AddressInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Webmozart\Assert\Assert;

final class AddressStreetEligibilityValidator extends ConstraintValidator
{
/** @var StreetEligibilityCheckerInterface */
private $streetEligibilityChecker;

public function __construct(StreetEligibilityCheckerInterface $streetEligibilityChecker)
{
$this->streetEligibilityChecker = $streetEligibilityChecker;
}

public function validate($address, Constraint $constraint): void
{
Assert::isInstanceOf($address, AddressInterface::class);
Assert::isInstanceOf($constraint, AddressStreetEligibility::class);

if (!$this->streetEligibilityChecker->isEligible($address)) {
$this->context
->buildViolation($constraint->message)
->atPath('street')
->addViolation()
;
}
}
}
23 changes: 23 additions & 0 deletions src/Validator/Constraints/AddressStreetEligibility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusQuickpayPlugin\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

final class AddressStreetEligibility extends Constraint
{
/** @var string */
public $message = 'setono_sylius_quickpay.address.street_eligibility';

public function validatedBy(): string
{
return 'setono_sylius_quickpay_address_street_eligibility_validator';
}

public function getTargets(): string
{
return self::CLASS_CONSTRAINT;
}
}
16 changes: 16 additions & 0 deletions tests/Application/config/validator/Address.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Addressing\Model\Address">
<constraint name="Setono\SyliusQuickpayPlugin\Validator\Constraints\AddressStreetEligibility">
<option name="message">setono_sylius_quickpay.address.street_eligibility</option>
<option name="groups">
<value>sylius_shipping_address_update</value>
<value>sylius_checkout_complete</value>
<value>sylius</value>
</option>
</constraint>
</class>
</constraint-mapping>

0 comments on commit 7684f8c

Please sign in to comment.