custom/plugins/PaymentPlugin/src/PaymentPlugin.php line 30

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Virgin\PaymentPlugin;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\Context;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  9. use Shopware\Core\Framework\Plugin;
  10. use Shopware\Core\Framework\Plugin\Context\ActivateContext;
  11. use Shopware\Core\Framework\Plugin\Context\DeactivateContext;
  12. use Shopware\Core\Framework\Plugin\Context\InstallContext;
  13. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  14. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  15. use Shopware\Core\Framework\Plugin\Util\PluginIdProvider;
  16. use Shopware\Core\System\CustomField\CustomFieldTypes;
  17. use Virgin\PaymentPlugin\Service\ClubPaymentHandler;
  18. use Virgin\PaymentPlugin\Service\DirectDebitPaymentHandler;
  19. use Virgin\PaymentPlugin\Service\NewPaymentAgreementHandler;
  20. use Virgin\PaymentPlugin\Service\NexiExternalLinkPaymentHandler;
  21. use Virgin\PaymentPlugin\Service\NexiPaymentHandler;
  22. use Virgin\PaymentPlugin\Service\SuperPromoPaymentHandler;
  23. /**
  24. * Class PaymentPlugin
  25. * @package Virgin\PaymentPlugin
  26. */
  27. class PaymentPlugin extends Plugin
  28. {
  29. const CLUB_PAYMENT_TYPE = 1;
  30. const DIRECT_DEBIT_PAYMENT_TYPE = 2;
  31. const NEXY_PAYMENT_TYPE = 3;
  32. const SUPER_PROMO_PAYMENT_TYPE = 4;
  33. const NEXY_PAYMENT_TYPE_EXTERNAL = 5;
  34. const NEW_PAYMENT_AGREEMENT_TYPE = 6;
  35. public function install(InstallContext $context): void
  36. {
  37. $paymentFields =
  38. [
  39. [
  40. 'name' => 'payment_type',
  41. 'type' => CustomFieldTypes::INT,
  42. 'config' => [
  43. 'componentName' => 'sw-field',
  44. 'type' => 'number',
  45. 'numbertype'=> 'int',
  46. 'customFieldType' => "number",
  47. 'customFieldPosition' => 1,
  48. 'label' => [
  49. 'en-GB' => 'payment type identifier',
  50. ],
  51. ],
  52. ],
  53. ];
  54. $this->addPaymentCustomFields($paymentFields);
  55. $this->addPaymentMethod($context->getContext());
  56. }
  57. public function uninstall(UninstallContext $context): void
  58. {
  59. // Only set the payment method to inactive when uninstalling. Removing the payment method would
  60. // cause data consistency issues, since the payment method might have been used in several orders
  61. $this->setPaymentMethodIsActive(false, $context->getContext());
  62. }
  63. public function activate(ActivateContext $context): void
  64. {
  65. $this->setPaymentMethodIsActive(true, $context->getContext());
  66. parent::activate($context);
  67. }
  68. public function deactivate(DeactivateContext $context): void
  69. {
  70. $this->setPaymentMethodIsActive(false, $context->getContext());
  71. parent::deactivate($context);
  72. }
  73. public function update(UpdateContext $context): void
  74. {
  75. $orderFields = [
  76. [
  77. 'name' => 'payment_agreement_reference',
  78. 'type' => CustomFieldTypes::TEXT,
  79. 'config' => [
  80. 'componentName' => 'sw-field',
  81. 'type' => 'text',
  82. 'customFieldType' => 'text',
  83. 'customFieldPosition' => 1,
  84. 'label' => [
  85. 'en-GB' => 'Payment Agreement Reference',
  86. ],
  87. ],
  88. ]
  89. ];
  90. $this->addOrderCustomFields($orderFields, 'payment_option', 'Payment option');
  91. $paymentMethodExists = $this->getPaymentMethods();
  92. /** @var PluginIdProvider $pluginIdProvider */
  93. $pluginIdProvider = $this->container->get(PluginIdProvider::class);
  94. $pluginId = $pluginIdProvider->getPluginIdByBaseClass(get_class($this), $context->getContext());
  95. $connection = $this->container->get(Connection::class);
  96. $builder = $connection->createQueryBuilder();
  97. $salesChannelsId = $builder->select(['LOWER(HEX(sct.sales_channel_id ))'])
  98. ->from('sales_channel_translation sct')
  99. ->where('sct.name = :name')
  100. ->setParameter('name', "Virgin Active")
  101. ->execute()
  102. ->fetch(\PDO::FETCH_COLUMN);
  103. $newPaymentMethods = [
  104. [
  105. // payment handler will be selected by the identifier
  106. 'handlerIdentifier' => NewPaymentAgreementHandler::class,
  107. 'name' => 'Accordo di pagamento precedente',
  108. 'description' => 'Accordo di pagamento',
  109. 'pluginId' => $pluginId,
  110. 'salesChannels' => [
  111. ['id' => strtolower($salesChannelsId)]
  112. ],
  113. 'active'=>true,
  114. 'customFields' => [
  115. 'payment_type' => self::NEW_PAYMENT_AGREEMENT_TYPE
  116. ],
  117. ]
  118. ];
  119. /** @var EntityRepositoryInterface $paymentRepository */
  120. $paymentRepository = $this->container->get('payment_method.repository');
  121. foreach ($newPaymentMethods as $newPaymentMethod){
  122. if ($paymentMethodExists) {
  123. if (in_array($newPaymentMethod['handlerIdentifier'], $paymentMethodExists)){
  124. continue;
  125. }
  126. else{
  127. $paymentRepository->create([$newPaymentMethod], $context->getContext());
  128. }
  129. }else{
  130. $paymentRepository->create([$newPaymentMethod], $context->getContext());
  131. }
  132. }
  133. }
  134. private function addPaymentMethod(Context $context): void
  135. {
  136. $paymentMethodExists = $this->getPaymentMethods();
  137. /** @var PluginIdProvider $pluginIdProvider */
  138. $pluginIdProvider = $this->container->get(PluginIdProvider::class);
  139. $pluginId = $pluginIdProvider->getPluginIdByBaseClass(get_class($this), $context);
  140. $connection = $this->container->get(Connection::class);
  141. $builder = $connection->createQueryBuilder();
  142. $salesChannelsId = $builder->select(['LOWER(HEX(sct.sales_channel_id ))'])
  143. ->from('sales_channel_translation sct')
  144. ->where('sct.name = :name')
  145. ->setParameter('name', "Virgin Active")
  146. ->execute()
  147. ->fetch(\PDO::FETCH_COLUMN);
  148. $newPaymentMethods = [
  149. [
  150. // payment handler will be selected by the identifier
  151. 'handlerIdentifier' => ClubPaymentHandler::class,
  152. 'name' => 'Pagamento al club',
  153. 'description' => 'Pay at the club',
  154. 'pluginId' => $pluginId,
  155. 'salesChannels' => [
  156. ['id' => strtolower($salesChannelsId)]
  157. ],
  158. 'active'=>true,
  159. 'customFields' => [
  160. 'payment_type' => self::CLUB_PAYMENT_TYPE
  161. ],
  162. ],
  163. [
  164. // payment handler will be selected by the identifier
  165. 'handlerIdentifier' => DirectDebitPaymentHandler::class,
  166. 'name' => 'Addebito diretto',
  167. 'description' => 'Direct debit',
  168. 'pluginId' => $pluginId,
  169. 'salesChannels' => [
  170. ['id' => strtolower($salesChannelsId)]
  171. ],
  172. 'active'=>true,
  173. 'customFields' => [
  174. 'payment_type' => self::DIRECT_DEBIT_PAYMENT_TYPE
  175. ],
  176. ],
  177. [
  178. // payment handler will be selected by the identifier
  179. 'handlerIdentifier' => NexiPaymentHandler::class,
  180. 'name' => 'Pagamento Nexi',
  181. 'description' => 'Nexi payment',
  182. 'pluginId' => $pluginId,
  183. 'salesChannels' => [
  184. ['id' => strtolower($salesChannelsId)]
  185. ],
  186. 'active'=>true,
  187. 'customFields' => [
  188. 'payment_type' => self::NEXY_PAYMENT_TYPE
  189. ],
  190. ],
  191. [
  192. // payment handler will be selected by the identifier
  193. 'handlerIdentifier' => SuperPromoPaymentHandler::class,
  194. 'name' => 'Super promo pagamento',
  195. 'description' => 'Super promo payment',
  196. 'pluginId' => $pluginId,
  197. 'salesChannels' => [
  198. ['id' => strtolower($salesChannelsId)]
  199. ],
  200. 'active'=>false,
  201. 'customFields' => [
  202. 'payment_type' => self::SUPER_PROMO_PAYMENT_TYPE
  203. ],
  204. ],
  205. [
  206. // payment handler will be selected by the identifier
  207. 'handlerIdentifier' => NexiExternalLinkPaymentHandler::class,
  208. 'name' => 'Pagamento Nexi Link',
  209. 'description' => 'Pagamento nexi tramite link',
  210. 'pluginId' => $pluginId,
  211. 'salesChannels' => [
  212. ['id' => strtolower($salesChannelsId)]
  213. ],
  214. 'active'=>true,
  215. 'customFields' => [
  216. 'payment_type' => self::NEXY_PAYMENT_TYPE_EXTERNAL
  217. ],
  218. ]
  219. ];
  220. /** @var EntityRepositoryInterface $paymentRepository */
  221. $paymentRepository = $this->container->get('payment_method.repository');
  222. foreach ($newPaymentMethods as $newPaymentMethod){
  223. if ($paymentMethodExists) {
  224. if (in_array($newPaymentMethod['handlerIdentifier'], $paymentMethodExists)){
  225. continue;
  226. }
  227. else{
  228. $paymentRepository->create([$newPaymentMethod], $context);
  229. }
  230. }else{
  231. $paymentRepository->create([$newPaymentMethod], $context);
  232. }
  233. }
  234. }
  235. private function setPaymentMethodIsActive(bool $active, Context $context): void
  236. {
  237. /** @var EntityRepositoryInterface $paymentRepository */
  238. $paymentRepository = $this->container->get('payment_method.repository');
  239. $paymentMethods = $this->getPaymentMethods();
  240. // Payment does not even exist, so nothing to (de-)activate here
  241. if (!$paymentMethods) {
  242. return;
  243. }
  244. foreach ($paymentMethods as $paymentMethod){
  245. $paymentCriteria = (new Criteria())->addFilter(new EqualsFilter('handlerIdentifier', $paymentMethod));
  246. $paymentId = $paymentRepository->searchIds($paymentCriteria, Context::createDefaultContext());
  247. $paymentMethod = [
  248. 'id' => $paymentId->getIds()[0],
  249. 'active' => $active,
  250. ];
  251. $paymentRepository->update([$paymentMethod], $context);
  252. }
  253. }
  254. private function getPaymentMethods(): ?array
  255. {
  256. /** @var EntityRepositoryInterface $paymentRepository */
  257. $paymentRepository = $this->container->get('payment_method.repository');
  258. // Fetch ID for update
  259. $paymentCriteria = (new Criteria())->addFilter(new EqualsAnyFilter('handlerIdentifier', [ClubPaymentHandler::class, NexiPaymentHandler::class, DirectDebitPaymentHandler::class, SuperPromoPaymentHandler::class, NexiExternalLinkPaymentHandler::class]));
  260. $payments = $paymentRepository->search($paymentCriteria, Context::createDefaultContext())->getElements();
  261. if (empty($payments)) {
  262. return null;
  263. }
  264. $paymentIdentifiers = [];
  265. foreach ($payments as $payment){
  266. array_push($paymentIdentifiers, $payment->getHandlerIdentifier());
  267. }
  268. return $paymentIdentifiers;
  269. }
  270. private function addPaymentCustomFields($paymentFields)
  271. {
  272. /** @var $customFieldSetRepository */
  273. $customFieldSetRepository = $this->container->get('custom_field_set.repository');
  274. $customFieldRepository = $this->container->get('custom_field.repository');
  275. $context = Context::createDefaultContext();
  276. foreach ($paymentFields as $paymentField) {
  277. $criteria = new Criteria();
  278. $criteria->addFilter(
  279. new EqualsFilter('custom_field.name', $paymentField['name'])
  280. );
  281. $fieldId = $customFieldRepository->searchIds($criteria, $context)->firstId();
  282. if ($fieldId == null) {
  283. $createCustomFields[] = $paymentField;
  284. }
  285. }
  286. if (!empty($createCustomFields)) {
  287. $customFieldSetRepository->create([
  288. [
  289. 'name' => 'payment_type',
  290. 'customFields' => $createCustomFields,
  291. 'config' => [
  292. 'label' => [
  293. 'en-GB' => 'Payment type',
  294. ],
  295. ],
  296. 'relations' => [
  297. ['entityName' => 'payment_method'],
  298. ],
  299. ],
  300. ], $context);
  301. }
  302. }
  303. private function addOrderCustomFields($newOrderCustomFields, $setName, $label)
  304. {
  305. /** @var EntityRepositoryInterface $customFieldSetRepository */
  306. $customFieldSetRepository = $this->container->get('custom_field_set.repository');
  307. $customFieldRepository = $this->container->get('custom_field.repository');
  308. $context = Context::createDefaultContext();
  309. foreach ($newOrderCustomFields as $newOrderCustomField) {
  310. $criteria = new Criteria();
  311. $criteria->addFilter(
  312. new EqualsFilter('custom_field.name', $newOrderCustomField['name'])
  313. );
  314. $fieldId = $customFieldRepository->searchIds($criteria, $context)->firstId();
  315. if ($fieldId == null) {
  316. $createCustomFields[] = $newOrderCustomField;
  317. }
  318. }
  319. $criteria = new Criteria();
  320. $criteria->addFilter(
  321. new EqualsFilter('name', $setName)
  322. );
  323. $customFieldSetId = $customFieldSetRepository->searchIds($criteria, $context)->firstId();
  324. if (!empty($createCustomFields)) {
  325. if (null == $customFieldSetId) {
  326. $customFieldSetRepository->create([
  327. [
  328. 'name' => $setName,
  329. 'customFields' => $createCustomFields,
  330. 'config' => [
  331. 'label' => [
  332. 'en-GB' => $label,
  333. ],
  334. ],
  335. 'relations' => [
  336. ['entityName' => 'order'],
  337. ],
  338. ],
  339. ], $context);
  340. } else {
  341. $customFieldSetRepository->update(
  342. [
  343. [
  344. 'id' => $customFieldSetId,
  345. 'customFields' => $createCustomFields
  346. ]
  347. ], $context);
  348. }
  349. }
  350. }
  351. }