Backup
This commit is contained in:
parent
332e8982ec
commit
2632d08946
62
src/new/var/plugins/System/PSC/Mollie/Api/Base.php
Normal file
62
src/new/var/plugins/System/PSC/Mollie/Api/Base.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\Mollie\Api;
|
||||||
|
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
class Base
|
||||||
|
{
|
||||||
|
protected string $baseUrl = 'https://api.mollie.com';
|
||||||
|
|
||||||
|
protected \PSC\Shop\EntityBundle\Document\Shop $shop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var HttpClientInterface
|
||||||
|
*/
|
||||||
|
protected HttpClientInterface $client;
|
||||||
|
|
||||||
|
protected string $apiKey = '';
|
||||||
|
|
||||||
|
public function __construct(HttpClientInterface $client)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postV2(string $url, array $data): array
|
||||||
|
{
|
||||||
|
$response = $this->client->request('POST', $this->baseUrl . $url, [
|
||||||
|
'headers' => $this->buildHeaders(),
|
||||||
|
'json' => $data,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getV2(string $url): array
|
||||||
|
{
|
||||||
|
$response = $this->client->request('GET', $this->baseUrl . $url, [
|
||||||
|
'headers' => $this->buildHeaders(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildHeaders(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Authorization' => 'Bearer ' . $this->apiKey,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShop(\PSC\Shop\EntityBundle\Document\Shop $shop): void
|
||||||
|
{
|
||||||
|
$this->shop = $shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setApiKey(string $apiKey): void
|
||||||
|
{
|
||||||
|
$this->apiKey = $apiKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
src/new/var/plugins/System/PSC/Mollie/Api/CreatePayment.php
Normal file
84
src/new/var/plugins/System/PSC/Mollie/Api/CreatePayment.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\Mollie\Api;
|
||||||
|
|
||||||
|
use PSC\Shop\EntityBundle\Entity\ContactAddress;
|
||||||
|
|
||||||
|
class CreatePayment extends Base
|
||||||
|
{
|
||||||
|
protected ?ContactAddress $invoiceAddress = null;
|
||||||
|
protected string $description = '';
|
||||||
|
protected string $redirectUrl = '';
|
||||||
|
protected string $webhookUrl = '';
|
||||||
|
protected ?string $orderReference = null;
|
||||||
|
|
||||||
|
public function call(): array
|
||||||
|
{
|
||||||
|
return $this->postV2('/v2/payments', $this->buildData());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildData(): array
|
||||||
|
{
|
||||||
|
$basket = $_SESSION['Basket'];
|
||||||
|
|
||||||
|
$amount = round($basket['brutto'] - round($basket['GutscheinAbzug'], 2), 2);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'amount' => [
|
||||||
|
'currency' => 'EUR',
|
||||||
|
'value' => number_format($amount, 2, '.', ''),
|
||||||
|
],
|
||||||
|
'description' => $this->description !== '' ? $this->description : 'Bestellung',
|
||||||
|
'redirectUrl' => $this->redirectUrl,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->webhookUrl !== '') {
|
||||||
|
$data['webhookUrl'] = $this->webhookUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->orderReference !== null) {
|
||||||
|
$data['metadata'] = [
|
||||||
|
'order_reference' => $this->orderReference,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->invoiceAddress !== null) {
|
||||||
|
$data['billingAddress'] = [
|
||||||
|
'givenName' => $this->invoiceAddress->getFirstname(),
|
||||||
|
'familyName' => $this->invoiceAddress->getLastname(),
|
||||||
|
'email' => $this->invoiceAddress->getEmail(),
|
||||||
|
'streetAndNumber' => trim($this->invoiceAddress->getStreet() . ' ' . $this->invoiceAddress->getHouseNumber()),
|
||||||
|
'postalCode' => $this->invoiceAddress->getZip(),
|
||||||
|
'city' => $this->invoiceAddress->getCity(),
|
||||||
|
'country' => $this->invoiceAddress->getCountry(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setInvoiceAddress(ContactAddress $invoiceAddress): void
|
||||||
|
{
|
||||||
|
$this->invoiceAddress = $invoiceAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDescription(string $description): void
|
||||||
|
{
|
||||||
|
$this->description = $description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRedirectUrl(string $redirectUrl): void
|
||||||
|
{
|
||||||
|
$this->redirectUrl = $redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setWebhookUrl(string $webhookUrl): void
|
||||||
|
{
|
||||||
|
$this->webhookUrl = $webhookUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOrderReference(?string $orderReference): void
|
||||||
|
{
|
||||||
|
$this->orderReference = $orderReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/new/var/plugins/System/PSC/Mollie/Api/GetPayment.php
Normal file
18
src/new/var/plugins/System/PSC/Mollie/Api/GetPayment.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\Mollie\Api;
|
||||||
|
|
||||||
|
class GetPayment extends Base
|
||||||
|
{
|
||||||
|
protected string $paymentId = '';
|
||||||
|
|
||||||
|
public function call(): array
|
||||||
|
{
|
||||||
|
return $this->getV2('/v2/payments/' . urlencode($this->paymentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPaymentId(string $paymentId): void
|
||||||
|
{
|
||||||
|
$this->paymentId = $paymentId;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/new/var/plugins/System/PSC/Mollie/Document/Mollie.php
Normal file
65
src/new/var/plugins/System/PSC/Mollie/Document/Mollie.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
namespace Plugin\System\PSC\Mollie\Document;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\EmbeddedDocument;
|
||||||
|
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
|
||||||
|
|
||||||
|
#[EmbeddedDocument]
|
||||||
|
class Mollie
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string $apiKey
|
||||||
|
*/
|
||||||
|
#[Field(type: 'string')]
|
||||||
|
protected $apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $testApiKey
|
||||||
|
*/
|
||||||
|
#[Field(type: 'string')]
|
||||||
|
protected $testApiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean $production
|
||||||
|
*/
|
||||||
|
#[Field(type: 'bool')]
|
||||||
|
protected $production;
|
||||||
|
|
||||||
|
public function getApiKey(): string
|
||||||
|
{
|
||||||
|
return (string)$this->apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setApiKey(?string $apiKey): void
|
||||||
|
{
|
||||||
|
$this->apiKey = $apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTestApiKey(): string
|
||||||
|
{
|
||||||
|
return (string)$this->testApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTestApiKey(?string $testApiKey): void
|
||||||
|
{
|
||||||
|
$this->testApiKey = $testApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isProduction(): bool
|
||||||
|
{
|
||||||
|
return (bool)$this->production;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProduction(bool $production): void
|
||||||
|
{
|
||||||
|
$this->production = $production;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the API key matching the configured mode.
|
||||||
|
*/
|
||||||
|
public function getActiveApiKey(): string
|
||||||
|
{
|
||||||
|
return $this->isProduction() ? $this->getApiKey() : $this->getTestApiKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
219
src/new/var/plugins/System/PSC/Mollie/Payment/Provider.php
Normal file
219
src/new/var/plugins/System/PSC/Mollie/Payment/Provider.php
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\System\PSC\Mollie\Payment;
|
||||||
|
|
||||||
|
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Plugin\System\PSC\Mollie\Api\CreatePayment;
|
||||||
|
use Plugin\System\PSC\Mollie\Api\GetPayment;
|
||||||
|
use Plugin\System\PSC\Mollie\Document\Mollie;
|
||||||
|
use PSC\Shop\EntityBundle\Entity\Contact;
|
||||||
|
use PSC\Shop\EntityBundle\Entity\ContactAddress;
|
||||||
|
use PSC\Shop\PaymentBundle\Document\Gatewaysettings;
|
||||||
|
use PSC\Shop\PaymentBundle\Provider\PaymentProvider;
|
||||||
|
use PSC\Shop\QueueBundle\Event\Order\Payed;
|
||||||
|
use PSC\Shop\QueueBundle\Service\Event\Manager;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\Form;
|
||||||
|
use Symfony\Component\Form\FormBuilder;
|
||||||
|
use Symfony\Component\Form\FormFactoryInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class Provider extends PaymentProvider
|
||||||
|
{
|
||||||
|
/** @var Form */
|
||||||
|
private $_formFactory = null;
|
||||||
|
private $_entityManager = null;
|
||||||
|
private $_doctrine_mongodb = null;
|
||||||
|
private \PSC\System\SettingsBundle\Service\Shop $shopService;
|
||||||
|
private Manager $eventManager;
|
||||||
|
private CreatePayment $createPaymentService;
|
||||||
|
private GetPayment $getPaymentService;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
CreatePayment $createPayment,
|
||||||
|
GetPayment $getPayment,
|
||||||
|
Manager $eventManager,
|
||||||
|
FormFactoryInterface $formFactory,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
DocumentManager $doctrine_mongodb,
|
||||||
|
\PSC\System\SettingsBundle\Service\Shop $shopService,
|
||||||
|
) {
|
||||||
|
$this->_formFactory = $formFactory;
|
||||||
|
$this->_entityManager = $entityManager;
|
||||||
|
$this->_doctrine_mongodb = $doctrine_mongodb;
|
||||||
|
$this->shopService = $shopService;
|
||||||
|
$this->eventManager = $eventManager;
|
||||||
|
$this->createPaymentService = $createPayment;
|
||||||
|
$this->getPaymentService = $getPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'Mollie';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'mollie';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveDocument(Gatewaysettings $settings, Form $form)
|
||||||
|
{
|
||||||
|
$doc = new Mollie();
|
||||||
|
|
||||||
|
$doc->setApiKey($form->get('mollie')->get('apiKey')->getData());
|
||||||
|
$doc->setTestApiKey($form->get('mollie')->get('testApiKey')->getData());
|
||||||
|
$doc->setProduction((bool) $form->get('mollie')->get('production')->getData());
|
||||||
|
|
||||||
|
$settings->setGatewayDocument($doc);
|
||||||
|
|
||||||
|
return $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubForm(Gatewaysettings $settings, FormBuilder $builder)
|
||||||
|
{
|
||||||
|
if (!$settings->getGatewayDocument()) {
|
||||||
|
$settings->setGatewayDocument(new Mollie());
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->add('production', CheckboxType::class, [
|
||||||
|
'label' => 'Production?',
|
||||||
|
'required' => false,
|
||||||
|
])->add('apiKey', TextType::class, [
|
||||||
|
'label' => 'Live API-Key',
|
||||||
|
'required' => false,
|
||||||
|
])->add('testApiKey', TextType::class, ['label' => 'Test API-Key', 'required' => false]);
|
||||||
|
|
||||||
|
$builder->get('production')->setData($settings->getGatewayDocument()->isProduction());
|
||||||
|
$builder->get('apiKey')->setData($settings->getGatewayDocument()->getApiKey());
|
||||||
|
$builder->get('testApiKey')->setData($settings->getGatewayDocument()->getTestApiKey());
|
||||||
|
|
||||||
|
return $builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTemplate()
|
||||||
|
{
|
||||||
|
return '@PluginSystemPSCMollie/settings.html.twig';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePayment(Request $request)
|
||||||
|
{
|
||||||
|
$invoice = $request->get('invoiceAddress');
|
||||||
|
|
||||||
|
/** @var ContactAddress $invoiceAddress */
|
||||||
|
$invoiceAddress = $this->_entityManager->getRepository(ContactAddress::class)->findOneBy(['uuid' => $invoice]);
|
||||||
|
|
||||||
|
/** @var Mollie $settings */
|
||||||
|
$settings = $this->getGatewaySettings()->getGatewayDocument();
|
||||||
|
|
||||||
|
$this->createPaymentService->setShop($this->shopDoc);
|
||||||
|
$this->createPaymentService->setApiKey($settings->getActiveApiKey());
|
||||||
|
$this->createPaymentService->setInvoiceAddress($invoiceAddress);
|
||||||
|
$this->createPaymentService->setRedirectUrl(
|
||||||
|
$this->getHost() . '/basket/finish?Data=finish&token=' . $request->get('hash') . '&paymentGateway=mollie',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->isPubliclyReachable($this->getHost())) {
|
||||||
|
$this->createPaymentService->setWebhookUrl($this->getHost() . '/payment/notify/mollie');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->createPaymentService->call();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die($e->getMessage());
|
||||||
|
return new RedirectResponse($this->getHost() . '/basket/finish?error=Mollie');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($response['_links']['checkout']['href'])) {
|
||||||
|
return new RedirectResponse($this->getHost() . '/basket/finish?error=Mollie');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RedirectResponse($response['_links']['checkout']['href']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleNotify(Request $request)
|
||||||
|
{
|
||||||
|
$paymentId = $request->request->get('id');
|
||||||
|
|
||||||
|
if (!$paymentId) {
|
||||||
|
return new Response('', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Mollie $settings */
|
||||||
|
$settings = $this->getGatewaySettings()->getGatewayDocument();
|
||||||
|
|
||||||
|
$this->getPaymentService->setApiKey($settings->getActiveApiKey());
|
||||||
|
$this->getPaymentService->setPaymentId($paymentId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$payment = $this->getPaymentService->call();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return new Response('', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($payment['status']) || $payment['status'] !== 'paid') {
|
||||||
|
return new Response('', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \PSC\Shop\EntityBundle\Document\Order $orderDoc */
|
||||||
|
$orderDoc = $this->_doctrine_mongodb
|
||||||
|
->getRepository('PSC\Shop\EntityBundle\Document\Order')
|
||||||
|
->findOneBy(['paymentRef' => (string) $paymentId]);
|
||||||
|
|
||||||
|
if (!$orderDoc) {
|
||||||
|
return new Response('', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \PSC\Shop\EntityBundle\Entity\Order $order */
|
||||||
|
$order = $this->_entityManager
|
||||||
|
->getRepository('PSC\Shop\EntityBundle\Entity\Order')
|
||||||
|
->findOneBy(['uid' => $orderDoc->getUid()]);
|
||||||
|
|
||||||
|
$order->setStatus(145);
|
||||||
|
$this->_entityManager->persist($order);
|
||||||
|
$this->_entityManager->flush();
|
||||||
|
|
||||||
|
$notify = new Payed();
|
||||||
|
$notify->setShop($this->getShopEntity()->getUID());
|
||||||
|
$notify->setOrder($order->getUuid());
|
||||||
|
|
||||||
|
$this->eventManager->addJob($notify);
|
||||||
|
|
||||||
|
return new Response('', 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function doPayment(Request $request) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mollie verlangt eine öffentlich erreichbare Webhook-URL.
|
||||||
|
* Auf lokalen Hosts (localhost, *.local, *.test, private IPs) wird der
|
||||||
|
* Webhook deshalb übersprungen, damit lokale Tests möglich sind.
|
||||||
|
*/
|
||||||
|
private function isPubliclyReachable(string $host): bool
|
||||||
|
{
|
||||||
|
$parsed = parse_url($host, PHP_URL_HOST) ?: $host;
|
||||||
|
$parsed = strtolower($parsed);
|
||||||
|
|
||||||
|
if ($parsed === 'localhost' || $parsed === '127.0.0.1' || $parsed === '::1') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_ends_with($parsed, '.local') || str_ends_with($parsed, '.test') || str_ends_with($parsed, '.localhost')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter_var($parsed, FILTER_VALIDATE_IP)) {
|
||||||
|
return (bool) filter_var(
|
||||||
|
$parsed,
|
||||||
|
FILTER_VALIDATE_IP,
|
||||||
|
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/new/var/plugins/System/PSC/Mollie/Plugin.php
Normal file
24
src/new/var/plugins/System/PSC/Mollie/Plugin.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
namespace Plugin\System\PSC\Mollie;
|
||||||
|
|
||||||
|
use PSC\System\PluginBundle\Plugin\Base;
|
||||||
|
|
||||||
|
class Plugin extends Base implements \PSC\System\PluginBundle\Interfaces\Plugin {
|
||||||
|
|
||||||
|
protected $name = 'Mollie Payment';
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return Plugin::Payment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return 'Stellt Unterstützung für Mollie bereit';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
Plugin\System\PSC\Mollie\:
|
||||||
|
resource: '../../*/*'
|
||||||
|
|
||||||
|
Plugin\System\PSC\Mollie\Payment\Provider:
|
||||||
|
tags:
|
||||||
|
- { name: paymentProvider }
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-md-4 form-control-label">{{ form_label(form.mollie.production) }}</label>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{{ form_widget(form.mollie.production, {attr: {'class': 'form-control'}}) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-md-4 form-control-label">{{ form_label(form.mollie.apiKey) }}</label>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{{ form_widget(form.mollie.apiKey, {attr: {'class': 'form-control'}}) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-md-4 form-control-label">{{ form_label(form.mollie.testApiKey) }}</label>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{{ form_widget(form.mollie.testApiKey, {attr: {'class': 'form-control'}}) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -6,6 +6,7 @@ changelog:
|
|||||||
- version: 2.3.5
|
- version: 2.3.5
|
||||||
datum: 01.04.2026
|
datum: 01.04.2026
|
||||||
changes:
|
changes:
|
||||||
|
- "Mollie Zahlungsanbieter"
|
||||||
- "Aktionen der An und Von Name wird jetzt ans Mailsystem übergeben"
|
- "Aktionen der An und Von Name wird jetzt ans Mailsystem übergeben"
|
||||||
- text: "CMS ContentBuilder Plugin kann aktiviert. (Custom Plugin und das Storefront Template muss die Ausgabe unterstützen)"
|
- text: "CMS ContentBuilder Plugin kann aktiviert. (Custom Plugin und das Storefront Template muss die Ausgabe unterstützen)"
|
||||||
images:
|
images:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user