- Issue created by @johnhanley
I spent the better part of a day trying to figure out how to automatically remove a role and revoke a license after issuing a refund. I finally cobbled together a working solution, so I thought Iβd share it in case someone ever needs to do something similar. As always, there are usually several ways to accomplish a task, some more efficient than others. I suppose the same result could also be achieved with Rules. Feel free to chime in if you know of a better approach.
Anyway, the task can be accomplishment with an EventSubcriber and services.yml file. Change the constant values to suit your particular use case.
custom.services.yml
services:
custom.payment_subscriber:
class: Drupal\custom\EventSubscriber\PaymentRefundSubscriber
tags:
- { name: event_subscriber }
/src/EventSubscriber/PaymentRefundSubscriber.php
<?php
namespace Drupal\custom\EventSubscriber;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_license\Entity\LicenseInterface;
use Drupal\user\UserInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Reacts to payment refunds: removes a specific user role and revokes licenses for a specific product type.
*/
class PaymentRefundSubscriber implements EventSubscriberInterface {
/**
* The user role to remove.
*/
const USER_ROLE = 'teacher';
/**
* The product type to check for licenses.
*/
const PRODUCT_TYPE = 'access_plan';
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
'commerce_payment.post_transition' => 'onPaymentPostTransition',
];
}
/**
* Removes the user role defined in USER_ROLE and revokes licenses
* for products defined in PRODUCT_TYPE when a payment is refunded.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The workflow transition event for the payment.
*/
public function onPaymentPostTransition(WorkflowTransitionEvent $event) {
$payment = $event->getEntity();
if (!$payment instanceof PaymentInterface) {
return;
}
$transition = $event->getTransition();
if ($transition->getToState()->getId() !== 'refunded') {
return;
}
$order = $payment->getOrder();
if (!$order instanceof OrderInterface) {
return;
}
$user = $order->getCustomer();
if ($user instanceof UserInterface && $user->hasRole(self::USER_ROLE)) {
// Remove the user role defined in USER_ROLE.
$user->removeRole(self::USER_ROLE);
$user->save();
}
// Revoke any active licenses linked to the order items for the product type defined in PRODUCT_TYPE.
foreach ($order->getItems() as $order_item) {
/** @var LicenseInterface $license */
$license = $order_item->get('license')->entity;
if (!$license instanceof LicenseInterface) {
continue;
}
$purchased_entity = $order_item->getPurchasedEntity();
if (!$purchased_entity || $purchased_entity->bundle() !== self::PRODUCT_TYPE) {
continue;
}
// Revoke the license if allowed.
if ($license->getState()->isTransitionAllowed('revoke')) {
$license->getState()->applyTransitionById('revoke');
$license->save();
}
}
}
}
Active
3.0
Documentation