In this blog, you are going to learn “How to integrate the payment method in shopware 6.”
I hope you know the directory structure of Shopware 6 plugin, if you don’t know, see here- https://docs.shopware.com/en/shopware-platform-dev-en/internals/directory-structure.
There is a two way of integrate the payment methods:-
one is Synchronous and second is Asynchronous.
Both interface method contains transaction id, order details, amount, a return URL , payment method information and language information.
In the Asynchronous interface handler return the redirect response to redirect the customer to an external payment provider. It also contain the return URL. External API return the error AsyncPaymentProcessException
so that Shopware handle the exception.
In the Synchronous interface handler doesn’t return the any redirect response. It basically use for internal purpose. You can used them according to your need.
Let’s take the example of synchronous methods:-
TestPaymentHandler.php
<?php declare(strict_types=1); namespace Webkul\Test\Service; use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\SynchronousPaymentHandlerInterface; use Shopware\Core\Checkout\Payment\Cart\SyncPaymentTransactionStruct; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; class TestPaymentHandler implements SynchronousPaymentHandlerInterface { /** * @var OrderTransactionStateHandler */ private $transactionStateHandler; /** * @var EntityRepositoryInterface */ private $testRepository; public function __construct( OrderTransactionStateHandler $transactionStateHandler, EntityRepositoryInterface $testRepository ) { $this->transactionStateHandler = $transactionStateHandler; $this->testRepository = $testRepository; } public function pay(SyncPaymentTransactionStruct $transaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): void { // demo example you can do your logic $test = $this->testRepository->search( (new Criteria()) ->addFilter(new EqualsFilter('customerId', $salesChannelContext->getCustomer()->getId())), Context::createDefaultContext() )->first(); $updatetest = [ 'id' => $test->getId(), 'amount' => (float)($test->getAmount() - ($transaction->getOrderTransaction()->getAmount()->getTotalPrice()/ $salesChannelContext->getCurrency()->getFactor())) ]; $this->testRepository->upsert([$updatetest], Context::createDefaultContext()); //SyncPaymentProcessException $context = $salesChannelContext->getContext(); $this->transactionStateHandler->paid($transaction->getOrderTransaction()->getId(), $context); //do your stuff } }
Create your own payment handler class and implements SynchronousPaymentHandlerInterface
so that when you go with checkout process this class is called and add the tag shopware.payment.method.sync
from the tag shopware knows that service is type of synchronous payment handler and must register your payment handler service in the services.xml file.
services.xml
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="Webkul\Test\Service\TestPaymentHandler"> <argument type="service" id="Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler"/> <argument type="service" id="wk_test.repository" /> <tag name="shopware.payment.method.sync" /> </service> <service id="Webkul\Test\Core\Content\Test\TestDefinition"> <tag name="shopware.entity.definition" entity="wk_test" /> </service> </services> </container>
Your handler is not handling any payment method, so create payment method.
WebkulTest.php
<?php declare(strict_types=1); namespace Webkul\Test; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Shopware\Core\Framework\Plugin; use Shopware\Core\Framework\Plugin\Context\ActivateContext; use Shopware\Core\Framework\Plugin\Context\DeactivateContext; use Shopware\Core\Framework\Plugin\Context\InstallContext; use Shopware\Core\Framework\Plugin\Context\UninstallContext; use Shopware\Core\Framework\Plugin\Util\PluginIdProvider; use Shopware\Core\Framework\Uuid\Uuid; use Webkul\Test\Service\TestPaymentHandler; use Doctrine\DBAL\Connection; class WebkulTest extends Plugin { public function install(InstallContext $context): void { $this->addPaymentMethod($context->getContext()); } public function uninstall(UninstallContext $context): void { $this->setPaymentMethodIsActive(false, $context->getContext()); parent:: uninstall($context); if ($context->keepUserData()) { return; } $connection = $this->container->get(Connection::class); $connection->executeUpdate('DROP TABLE IF EXISTS `wk_test`'); } public function activate(ActivateContext $context): void { $this->setPaymentMethodIsActive(true, $context->getContext()); parent::activate($context); } public function deactivate(DeactivateContext $context): void { $this->setPaymentMethodIsActive(false, $context->getContext()); parent::deactivate($context); } private function addPaymentMethod(Context $context): void { $paymentMethodExists = $this->getPaymentMethodId(); if ($paymentMethodExists) { return; } /** @var PluginIdProvider $pluginIdProvider */ $pluginIdProvider = $this->container->get(PluginIdProvider::class); $pluginId = $pluginIdProvider->getPluginIdByBaseClass(get_class($this), $context); $languageRepo = $this->container->get('language.repository'); $languageEN = $languageRepo->search((new Criteria())->addFilter(new EqualsFilter('name','English')),Context::createDefaultContext())->first()->getId(); $languageDE = $languageRepo->search((new Criteria())->addFilter(new EqualsFilter('name','Deutsch')),Context::createDefaultContext())->first()->getId(); $paymentId = Uuid::randomHex(); $PaymentData = [ 'id' => $paymentId, 'handlerIdentifier' => TestPaymentHandler::class, 'pluginId' => $pluginId, 'name' => 'Test payment', 'description' => 'Payment' ]; /** @var EntityRepositoryInterface $paymentRepository */ $paymentRepository = $this->container->get('payment_method.repository'); $paymentTransRepository = $this->container->get('payment_method_translation.repository'); $paymentRepository->create([$PaymentData], $context); $paymentTransRepository->upsert([ [ 'paymentMethodId' => $paymentId, 'languageId' => $languageEN, 'name' => 'Test Payment', 'description' => 'Payment' ], [ 'paymentMethodId' => $paymentId, 'languageId' => $languageDE, 'name' => 'Test Payment', 'description' => 'Zahlung' ] ], $context); } private function setPaymentMethodIsActive(bool $active, Context $context): void { /** @var EntityRepositoryInterface $paymentRepository */ $paymentRepository = $this->container->get('payment_method.repository'); $paymentMethodId = $this->getPaymentMethodId(); if (!$paymentMethodId) { return; } $paymentMethod = [ 'id' => $paymentMethodId, 'active' => $active, ]; $paymentRepository->update([$paymentMethod], $context); } private function getPaymentMethodId(): ?string { /** @var EntityRepositoryInterface $paymentRepository */ $paymentRepository = $this->container->get('payment_method.repository'); $paymentCriteria = (new Criteria())->addFilter(new EqualsFilter('handlerIdentifier', TestPaymentHandler::class)); return $paymentRepository->searchIds($paymentCriteria, Context::createDefaultContext())->firstId(); } }
The payment method can be added to the system while installing your plugin in the install
method, you actually start by creating a new payment method. he activate
method and deactivate
method just do that, activating and deactivating the payment method.
Now your payment method is created and payment handler service is working with your payment method.
Hope it will help you. Thanks for reading. Happy Coding 🙂
Thank You.
Be the first to comment.