Skip to content

Add payment logging #610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/log/commerce_log.commerce_log_categories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ commerce_cart:
commerce_order:
label: Order
entity_type: commerce_order

commerce_payment:
label: Payment
entity_type: commerce_payment
33 changes: 33 additions & 0 deletions modules/log/commerce_log.commerce_log_templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,36 @@ order_canceled:
category: commerce_order
label: 'Order canceled'
template: '<p>The order was canceled.</p>'

payment_authorized:
category: commerce_payment
label: 'Payment authorized'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was authorized.</p>'
payment_voided:
category: commerce_payment
label: 'Payment voided'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was voided.</p>'
payment_expired:
category: commerce_payment
label: 'Payment expired'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was expired.</p>'
payment_authorized_captured:
category: commerce_payment
label: 'Payment authorized and captured'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was authorized and captured.</p>'
payment_partially_captured:
category: commerce_payment
label: 'Payment partially captured'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was partially captured ({{ captured_amount }}).</p>'
payment_captured:
category: commerce_payment
label: 'Payment captured'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was fully captured.</p>'
payment_partially_refunded:
category: commerce_payment
label: 'Payment partially refunded'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was partially refunded ({{ refunded_amount }}).</p>'
payment_refunded:
category: commerce_payment
label: 'Payment refunded'
template: '<p>Payment <em>{{ payment_remote_id }}</em> was fully refunded.</p>'
4 changes: 3 additions & 1 deletion modules/log/commerce_log.module
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
function commerce_log_preprocess_commerce_order(&$variables) {
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $variables['elements']['#commerce_order'];
$order_payments = \Drupal::entityTypeManager()->getStorage('commerce_payment')->loadByProperties(['order_id' => $order->id()]);
$entity_ids = implode(',', array_merge([$order->id()], array_keys($order_payments)));
$variables['order']['activity'] = [
'#type' => 'view',
'#name' => 'commerce_activity',
'#display_id' => 'default',
'#arguments' => [$order->id(), 'commerce_order'],
'#arguments' => [$entity_ids, 'commerce_order,commerce_payment'],
'#embed' => TRUE,
'#title' => t('Order activity'),
];
Expand Down
7 changes: 3 additions & 4 deletions modules/log/config/install/views.view.commerce_activity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ display:
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: some
type: none
options:
items_per_page: 5
offset: 0
style:
type: table
Expand Down Expand Up @@ -316,7 +315,7 @@ display:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
break_phrase: true
not: false
entity_type: commerce_log
entity_field: source_entity_id
Expand Down Expand Up @@ -358,7 +357,7 @@ display:
case: none
path_case: none
transform_dash: false
break_phrase: false
break_phrase: true
entity_type: commerce_log
entity_field: source_entity_type
plugin_id: string
Expand Down
5 changes: 5 additions & 0 deletions modules/log/src/CommerceLogServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public function register(ContainerBuilder $container) {
->addTag('event_subscriber')
->addArgument(new Reference('entity_type.manager'));
}
if (isset($modules['commerce_payment'])) {
$container->register('commerce_log.payment_subscriber', 'Drupal\commerce_log\EventSubscriber\PaymentEventSubscriber')
->addTag('event_subscriber')
->addArgument(new Reference('entity_type.manager'));
}
}

}
214 changes: 214 additions & 0 deletions modules/log/src/EventSubscriber/PaymentEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
<?php

namespace Drupal\commerce_log\EventSubscriber;

use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_payment\Event\PaymentEvent;
use Drupal\commerce_payment\Event\PaymentEvents;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PaymentEventSubscriber implements EventSubscriberInterface {

/**
* The log storage.
*
* @var \Drupal\commerce_log\LogStorageInterface
*/
protected $logStorage;

/**
* Constructs a new PaymentEventSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->logStorage = $entity_type_manager->getStorage('commerce_log');
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [
'commerce_payment.authorize.pre_transition' => ['onAuthorizeTransition', -100],
'commerce_payment.void.pre_transition' => ['onVoidTransition', -100],
'commerce_payment.expire.pre_transition' => ['onExpireTransition', -100],
'commerce_payment.authorize_capture.pre_transition' => ['onAuthorizeCaptureTransition', -100],
PaymentEvents::PAYMENT_AUTHORIZED => ['onAuthorize', -100],
PaymentEvents::PAYMENT_VOIDED => ['onVoid', -100],
PaymentEvents::PAYMENT_EXPIRED => ['onExpire', -100],
PaymentEvents::PAYMENT_AUTHORIZED_CAPTURED => ['onAuthorizeCapture', -100],
PaymentEvents::PAYMENT_PARTIALLY_CAPTURED => ['onPartialCapture', -100],
PaymentEvents::PAYMENT_CAPTURED => ['onCapture', -100],
PaymentEvents::PAYMENT_PARTIALLY_REFUNDED => ['onPartialRefund', -100],
PaymentEvents::PAYMENT_REFUNDED => ['onRefund', -100],
];
return $events;
}

/**
* Creates a log when a payment is authorized.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function onAuthorizeTransition(WorkflowTransitionEvent $event) {
$this->dispatch(PaymentEvents::PAYMENT_AUTHORIZED, $event->getEntity());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this log?

}

/**
* Creates a log when a payment is voided.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function onVoidTransition(WorkflowTransitionEvent $event) {
$this->dispatch(PaymentEvents::PAYMENT_VOIDED, $event->getEntity());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no logging?

}

/**
* Creates a log when a payment is expired.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function onExpireTransition(WorkflowTransitionEvent $event) {
$this->dispatch(PaymentEvents::PAYMENT_EXPIRED, $event->getEntity());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And on through the rest of this subscriber...

}

/**
* Creates a log when a payment is authorized and captured.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function onAuthorizeCaptureTransition(WorkflowTransitionEvent $event) {
$this->dispatch(PaymentEvents::PAYMENT_AUTHORIZED_CAPTURED, $event->getEntity());
}

/**
* Dispatches a PaymentEvent for a payment.
*
* @param string $event_name
* A name of the payment event to dispatch.
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* A payment to use for dispatching the event.
*/
private function dispatch($event_name, PaymentInterface $payment) {
/** @var \Drupal\commerce_payment\Event\PaymentEvent $event */
$event = new PaymentEvent($payment);
/** @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher->dispatch($event_name, $event);
}

/**
* Creates a log when a payment is authorized.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onAuthorize(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_authorized', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

/**
* Creates a log when a payment is voided.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onVoid(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_voided', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

/**
* Creates a log when a payment is expired.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onExpire(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_expired', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

/**
* Creates a log when a payment is authorized and captured.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onAuthorizeCapture(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_authorized_captured', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

/**
* Creates a log when a payment is partially captured.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onPartialCapture(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_partially_captured', [
'payment_remote_id' => $payment->getRemoteId(),
'captured_amount' => $event->getAmount(),
])->save();
}

/**
* Creates a log when a payment is fully captured.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onCapture(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_captured', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

/**
* Creates a log when a payment is partially refunded.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onPartialRefund(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_partially_refunded', [
'payment_remote_id' => $payment->getRemoteId(),
'refunded_amount' => $event->getAmount(),
])->save();
}

/**
* Creates a log when a payment is fully refunded.
*
* @param \Drupal\commerce_payment\Event\PaymentEvent $event
* The payment event.
*/
public function onRefund(PaymentEvent $event) {
$payment = $event->getPayment();
$this->logStorage->generate($payment, 'payment_refunded', [
'payment_remote_id' => $payment->getRemoteId(),
])->save();
}

}
1 change: 1 addition & 0 deletions modules/payment/src/Entity/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* bundle_plugin_type = "commerce_payment_type",
* handlers = {
* "access" = "Drupal\commerce_payment\PaymentAccessControlHandler",
* "event" = "Drupal\commerce_payment\Event\PaymentEvent",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary if we state_machine

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, because payments do not use transitions.

* "list_builder" = "Drupal\commerce_payment\PaymentListBuilder",
* "storage" = "Drupal\commerce_payment\PaymentStorage",
* "form" = {
Expand Down
68 changes: 68 additions & 0 deletions modules/payment/src/Event/PaymentEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Drupal\commerce_payment\Event;

use Drupal\commerce_payment\Entity\PaymentInterface;
use Drupal\commerce_price\Price;
use Symfony\Component\EventDispatcher\Event;

/**
* Defines the payment event.
*
* @see \Drupal\commerce_payment\Event\PaymentEvents
*/
class PaymentEvent extends Event {

/**
* The payment.
*
* @var \Drupal\commerce_payment\Entity\PaymentInterface
*/
protected $payment;

/**
* The payment operation amount.
*
* @var \Drupal\commerce_price\Price
*/
protected $amount;

/**
* Constructs a new PaymentEvent.
*
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* The payment.
*/
public function __construct(PaymentInterface $payment) {
$this->payment = $payment;
}

/**
* @param \Drupal\commerce_price\Price $amount
* The payment operation amount.
*/
public function setAmount(Price $amount) {
$this->amount = $amount;
}

/**
* Gets the payment operation amount.
*
* @return \Drupal\commerce_price\Price
* The payment operation amount.
*/
public function getAmount() {
return $this->amount;
}

/**
* Gets the payment.
*
* @return \Drupal\commerce_payment\Entity\PaymentInterface
* The payment.
*/
public function getPayment() {
return $this->payment;
}

}
Loading