Sylius: Get started
Available payment methods
Mollie for Sylius offers a wide range of payment methods that your customers can use to pay during checkout:
Alma, Apple Pay (incl. Apple Pay Direct), Bancontact, Billie, Credit/Debit cards, EPS, iDEAL; iDEAL in3, Klarna, PayPal, Przelewy24, KBC Payment Button, Belfius Pay Button, SEPA Bank Transfer, Vouchers.
For information on how to select the best payment methods for your business, refer to the Mollie Payment methods guide.
Features
Mollie for Sylius offers the following features to effectively manage your online payments:
- Customize the payment experience
- Localize your payment methods
- Offer and manage subscriptions
- Manage orders and payments
Install and connect
Enhance your store's payment options with Mollie.
Note
This user guide explains how to install, configure and use the standard Mollie integra- tion with Sylius. For information on how to customize your integration, read Additional resources for developers↗.
What you need to do in advance:
- Create and successfully log in to your Mollie account.
- Make sure that you use these package versions:
- php 7.2 or 8.0
- mollie/mollie-api-php 2.0
- sylius/admin-order-creation-plugin 0.12, 0.13 or 0.14
- sylius/refund-plugin 1.0
- sylius 1.9.0, 1.10.0, 1.11.0 or 1.12.0
- Install Composer.
- Ensure that you have NPM and Node installed.
Install
Install the back-end:
- Install the
Refund
plugin:
Note
- Make sure that
wkhtmltopdf
is installed.- Set the tool path in the
.env
file using theWKHTMLTOPDF_PATH
and
WKHTMLTOIMAGE_PATH
variables.
composer require sylius/refund-plugin
- Install Mollie for Sylius:
composer require mollie/sylius-plugin --no-scripts -w
- Update the
GatewayConfig
entity class with the following code: (with annotations)
<?php
declare(strict_types=1);
namespace App\Entity\Payment;
use Doctrine\ORM\Mapping as ORM;
use SyliusMolliePlugin\Entity\GatewayConfigInterface;
use SyliusMolliePlugin\Entity\GatewayConfigTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Sylius\Bundle\PayumBundle\Model\GatewayConfig as BaseGatewayConfig;
/**
* @ORM\Entity
* @ORM\Table(name="sylius_gateway_config")
*/
class GatewayConfig extends BaseGatewayConfig implements GatewayConfigInterface
{
use GatewayConfigTrait;
/**
* @var ArrayCollection
* @ORM\OneToMany(
* targetEntity="SyliusMolliePlugin\Entity\MollieGatewayConfig",
* mappedBy="gateway",
* orphanRemoval=true,
* cascade={"all"}
* )
*/
protected $mollieGatewayConfig;
public function __construct()
{
parent::__construct();
$this->mollieGatewayConfig = new ArrayCollection();
}
}
You can find more annotation examples under the tests/Application/src/Entity/* path.
If you don't use annotations, you can also define new Entity mapping inside your src/Resources/config/doctrine
directory:
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
<mapped-superclass name="App\Entity\Payment\GatewayConfig" table="sylius_gateway_config">
<one-to-many field="mollieGatewayConfig" target-entity="SyliusMolliePlugin\Entity\MollieGatewayConfig" mapped-by="gateway" orphan-removal="true">
<cascade>
<cascade-all />
</cascade>
</one-to-many>
</mapped-superclass>
</doctrine-mapping>
For an example, check tests/Application/src/Resources/config/doctrine/GatewayConfig.orm.xml file.
Override the GatewayConfig
resource:
# config/packages/_sylius.yaml
...
sylius_payum:
resources:
gateway_config:
classes:
model: App\Entity\Payment\GatewayConfig
- Update the
Order
entity class: (with annotations)
<?php
declare(strict_types=1);
namespace App\Entity\Order;
use SyliusMolliePlugin\Entity\OrderInterface;
use SyliusMolliePlugin\Entity\AbandonedEmailOrderTrait;
use SyliusMolliePlugin\Entity\RecurringOrderTrait;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Core\Model\Order as BaseOrder;
use Sylius\Component\Core\Model\OrderItemInterface;
/**
* @ORM\Entity
* @ORM\Table(name="sylius_order")
*/
class Order extends BaseOrder implements OrderInterface
{
use AbandonedEmailOrderTrait;
use RecurringOrderTrait;
/**
* @var bool
* @ORM\Column(type="boolean", name="abandoned_email")
*/
protected $abandonedEmail = false;
/**
* @var ?int
* @ORM\Column(type="integer", name="recurring_sequence_index", nullable=true)
*/
protected $recurringSequenceIndex;
/**
* @var MollieSubscriptionInterface|null
* @ORM\ManyToOne(targetEntity="SyliusMolliePlugin\Entity\MollieSubscription")
* @ORM\JoinColumn(name="subscription_id", fieldName="subscription", onDelete="RESTRICT")
*/
protected $subscription = null;
public function getRecurringItems(): Collection
{
return $this
->items
->filter(function (OrderItemInterface $orderItem) {
$variant = $orderItem->getVariant();
return $variant !== null
&& true === $variant->isRecurring();
})
;
}
public function getNonRecurringItems(): Collection
{
return $this
->items
->filter(function (OrderItemInterface $orderItem) {
$variant = $orderItem->getVariant();
return $variant !== null
&& false === $variant->isRecurring();
})
;
}
public function hasRecurringContents(): bool
{
return 0 < $this->getRecurringItems()->count();
}
public function hasNonRecurringContents(): bool
{
return 0 < $this->getNonRecurringItems()->count();
}
}
If you don't use annotations, you can also define new Entity mapping inside your src/Resources/config/doctrine
directory.
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
<mapped-superclass name="App\Entity\Order\Order" table="sylius_order">
<field name="abandonedEmail" type="boolean" column="abandoned_email"/>
</mapped-superclass>
</doctrine-mapping>
Override Order
resource:
# config/packages/_sylius.yaml
...
sylius_order:
resources:
order:
classes:
model: App\Entity\Order\Order
- Update the
Product
entity class with the following code:
<?php
declare(strict_types=1);
namespace App\Entity\Product;
use Doctrine\ORM\Mapping as ORM;
use SyliusMolliePlugin\Entity\ProductInterface;
use SyliusMolliePlugin\Entity\ProductTrait;
use Sylius\Component\Core\Model\Product as BaseProduct;
/**
* @ORM\Entity
* @ORM\Table(name="sylius_product")
*/
class Product extends BaseProduct implements ProductInterface
{
use ProductTrait;
/**
* @ORM\ManyToOne(targetEntity="SyliusMolliePlugin\Entity\ProductType")
* @ORM\JoinColumn(name="product_type_id", fieldName="productType", onDelete="SET NULL")
*/
protected $productType;
}
If you don't use annotations, you can also define new Entity mapping inside your src/Resources/config/doctrine
directory.
<?xml version="1.0" encoding="UTF-8" ?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
>
<entity name="App\Entity\Product\Product" table="sylius_product">
<many-to-one
field="productType"
target-entity="SyliusMolliePlugin\Entity\ProductType"
>
<join-column
name="product_type_id"
on-delete="SET NULL"
/>
</many-to-one>
</entity>
</doctrine-mapping>
Override Product resource:
# config/packages/_sylius.yaml
...
sylius_product:
resources:
product:
classes:
model: App\Entity\Product\Product
- Update the
ProductVariant
entity class with the following code:
<?php
declare(strict_types=1);
namespace App\Entity\Product;
use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Core\Model\ProductVariant as BaseProductVariant;
use Sylius\Component\Product\Model\ProductVariantTranslationInterface;
/**
* @ORM\Entity
* @ORM\Table(name="sylius_product_variant")
*/
class ProductVariant extends BaseProductVariant
{
use RecurringProductVariantTrait;
protected function createTranslation(): ProductVariantTranslationInterface
{
return new ProductVariantTranslation();
}
public function getName(): ?string
{
return parent::getName() ?: $this->getProduct()->getName();
}
}
Add RecurringProductVariantTrait
implementation:
<?php
declare(strict_types=1);
namespace App\Entity\Product;
use Doctrine\ORM\Mapping as ORM;
trait RecurringProductVariantTrait
{
/**
* @var bool
* @ORM\Column(type="boolean", name="recurring", nullable="false", options={"default":0})
*/
private bool $recurring = false;
/**
* @var ?int
* @ORM\Column(type="integer", name="recurring_times", nullable="true")
*/
private ?int $times = null;
/**
* @var ?string
* @ORM\Column(type="string", name="recurring_interval", nullable="true")
*/
private ?string $interval = null;
public function isRecurring(): bool
{
return $this->recurring;
}
public function setRecurring(bool $recurring): void
{
$this->recurring = $recurring;
}
public function getTimes(): ?int
{
return $this->times;
}
public function setTimes(?int $times): void
{
$this->times = $times;
}
public function getInterval(): ?string
{
return $this->interval;
}
public function setInterval(?string $interval): void
{
$this->interval = $interval;
}
}
If you don't use annotations, you can also define new Entity mapping inside your src/Resources/config/doctrine
directory.
<?xml version="1.0" encoding="UTF-8" ?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
>
<mapped-superclass name="App\Entity\Product\ProductVariant" table="sylius_product_variant">
<field name="recurring" type="boolean" column="recurring">
<options>
<option name="default">0</option>
</options>
</field>
<field name="times" type="integer" column="recurring_times" nullable="true"/>
<field name="interval" column="recurring_interval" nullable="true"/>
</mapped-superclass>
</doctrine-mapping>
Override ProductVariant resource:
# config/packages/_sylius.yaml
...
sylius_product:
resources:
product_variant:
classes:
model: App\Entity\Product\ProductVariant
- Ensure that the plugin dependency is added to your
config/bundles.php
file:
# config/bundles.php
return [
...
SyliusMolliePlugin\SyliusMolliePlugin::class => ['all' => true],
];
- Import required config in your
config/packages/_sylius.yaml
file:
# config/packages/_sylius.yaml
imports:
...
- { resource: "@SyliusMolliePlugin/Resources/config/config.yaml" }
- Add state machine configuration in
config/packages/_sylius.yaml
:
# config/packages/_sylius.yaml
winzou_state_machine:
sylius_order_checkout:
transitions:
complete:
from: [cart, addressed, shipping_selected, shipping_skipped, payment_selected, payment_skipped]
to: completed
- Add image directory parameter in config/packages/_sylius.yaml:
# config/packages/_sylius.yaml
parameters:
images_dir: "/media/image/"
- Import the routing in your
config/routes.yaml
file:
# config/routes.yaml
sylius_mollie_plugin:
resource: "@SyliusMolliePlugin/Resources/config/routing.yaml"
- Update your database
Apply migration to your database: (this is for the plugin fresh installation only)bin/console doctrine:migrations:migrate
In case if you are updating from older version of plugin (versions < 5.0), you will need to run the following commands before running migrate command.
bin/console doctrine:migrations:version --add --range-from='SyliusMolliePlugin\Migrations\Version20200513092722' --range-to='SyliusMolliePlugin\Migrations\Version20220211040328'
bin/console doctrine:migrations:execute --up 'SyliusMolliePlugin\Migrations\Version20231225151033'
After running all the above-mentioned commands, run migrate command:
bin/console doctrine:migrations:migrate
- Copy Sylius templates overridden in plugin to your templates directory (e.g templates/bundles/):
mkdir -p templates/bundles/SyliusAdminBundle/
mkdir -p templates/bundles/SyliusShopBundle/
mkdir -p templates/bundles/SyliusUiBundle/
mkdir -p templates/bundles/SyliusRefundPlugin/
cp -R vendor/mollie/sylius-plugin/tests/Application/templates/bundles/SyliusAdminBundle/* templates/bundles/SyliusAdminBundle/
cp -R vendor/mollie/sylius-plugin/tests/Application/templates/bundles/SyliusShopBundle/* templates/bundles/SyliusShopBundle/
cp -R vendor/mollie/sylius-plugin/tests/Application/templates/bundles/SyliusUiBundle/* templates/bundles/SyliusUiBundle/
cp -R vendor/mollie/sylius-plugin/tests/Application/templates/bundles/SyliusRefundPlugin/* templates/bundles/SyliusRefundPlugin/
- Install assets:
bin/console assets:install
Note: If you are running it on production, add the -e prod flag to this command.
- Add the payment link cronjob:
* * * * * /usr/bin/php /path/to/bin/console mollie:send-payment-link
- Download the domain validation file and place it on your server at:
public/.well-known/apple-developer-merchantid-domain-association
Install the front-end
- Installing assets without webpack
If you're not using webpack, you can install assets via:bin/console assets:install
And then import these already built assets into shop/admin _scripts and _styles .html.twig files: For example: templates/bundles/SyliusAdminBundle/_scripts.html.twig
using:
{{ asset('public/bundles/syliusmollieplugin/mollie/admin.css') }}
{{ asset('public/bundles/syliusmollieplugin/mollie/admin.js') }}
{{ asset('public/bundles/syliusmollieplugin/mollie/shop.css') }}
{{ asset('public/bundles/syliusmollieplugin/mollie/shop.js') }}
These assets are located in:
public/bundles/syliusmollieplugin/mollie/admin.css
public/bundles/syliusmollieplugin/mollie/admin.js
public/bundles/syliusmollieplugin/mollie/shop.css
public/bundles/syliusmollieplugin/mollie/shop.js
- Importing pre-built assets without webpack
Another way is to import already built assets directly from mollie source files:
vendor/mollie/sylius-plugin/src/Resources/public/mollie/admin.css
vendor/mollie/sylius-plugin/src/Resources/public/mollie/admin.js
vendor/mollie/sylius-plugin/src/Resources/public/mollie/shop.css
vendor/mollie/sylius-plugin/src/Resources/public/mollie/shop.js
- Using webpack
Require webpack bundle with composer:
composer require symfony/webpack-encore-bundle
Ensure the following configuration is present in config/packages/webpack_encore.yaml
:
webpack_encore:
output_path: "%kernel.project_dir%/public/build"
builds:
mollie-admin: "%kernel.project_dir%/public/build/admin"
mollie-shop: "%kernel.project_dir%/public/build/shop"
script_attributes:
defer: false
framework:
assets:
json_manifest_path: '%kernel.project_dir%/public/build/admin/manifest.json'
Ensure that mollie-shop-entry
and mollie-admin-entry
are present in webpackconfig.js
:
Encore.addEntry(
'mollie-shop-entry',
path.resolve(
__dirname,
'vendor/mollie/sylius-plugin/src/Resources/assets/shop/entry.js'
)
)
Encore.addEntry(
'mollie-admin-entry',
path.resolve(
__dirname,
'vendor/mollie/sylius-plugin/src/Resources/assets/admin/entry.js'
)
)
If you are using Sylius version <= 1.11 ensure that Node version 12 is currently used, otherwise Node version 14 should be used:
nvm install 12
nvm use 12
Ensure you have the following packages installed:
yarn add babel-preset-env bazinga-translator intl-messageformat lodash.get [email protected] [email protected] webpack-notifier
yarn add --dev @babel/[email protected] @babel/[email protected] @babel/[email protected] @symfony/[email protected]
Run gulp:
yarn run gulp
Build the front-end assets:
yarn install
yarn build
yarn encore production
Update the scheme, since webpack and asset require new tables that are not in the migrations:
php bin/console doctrine:schema:update --force
Connect
Mollie gives you two API keys to authenticate Sylius requests:
- Test key: Use this key when setting up and testing Mollie.
- Live key: Use this key after Mollie has approved your account and you are ready to accept live payments.
To connect with Mollie, follow these steps:
- Log in to your Mollie Dashboard.
- Select the organization in the top-left corner of the dashboard's home page.
Important
To comply with UK regulations, UK-based merchants have to select a UK-registered organization to ensure that they use the correct API keys.
- Go to More > Developers > API keys.
- Copy the API keys.
- Log in to Sylius.
- Open Configuration > Payment methods.
- Select +Create.
- Select Mollie or Mollie subscriptions.
- Mollie: Payment methods for products purchased on a non-recurring basis
- Mollie subscriptions: Payment methods for products purchased on a recurring basis
- Add a payment gateway code to identify the Mollie payment methods.
- In the Gateway configuration section, select Test from the drop-down menu.
- Paste the API keys into their respective fields.
- Select +Create.
- Select Edit next to the gateway.
- Select Load methods.
- Select Save changes.
Updated 3 months ago