Authorization fails when redeeming gift cards

Created on 6 September 2021, almost 3 years ago
Updated 7 February 2023, over 1 year ago

Problem/Motivation

Transactions are not authorized when commerce_giftcards are redeemed on the order.

Steps to reproduce

Buy something and apply a commerce_giftcard.

Proposed resolution

We have solved this for a client with the following custom event subscriber. It would be nice to move something similar upstream, an MR will follow.

<?php

declare(strict_types = 1);

namespace Drupal\myproject_commerce\EventSubscriber;

use Drupal\commerce_giftcard\GiftcardOrderManager;
use Drupal\commerce_klarna_payments\Bridge\UnitConverter;
use Drupal\commerce_klarna_payments\Event\RequestEvent;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Klarna\Payments\Model\OrderLine;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Modifies the request to be sent to Klarna.
 *
 * This is used to add an order line for gift card adjustments.
 * The order lines must be added when creating the session and when
 * creating the order, otherwise authorization will fail.
 *
 * @see \Drupal\commerce_klarna_payments\EventSubscriber\OrderTransitionSubscriber
 */
final class KlarnaBuildSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * Gift card order manager.
   *
   * @var \Drupal\commerce_giftcard\GiftcardOrderManager|null
   */
  private ?GiftcardOrderManager $giftcardOrderManager;

  /**
   * Construct a new KlarnaSessionCreateSubscriber.
   *
   * @param \Drupal\commerce_giftcard\GiftcardOrderManager|null $giftcardOrderManager
   *   Gift card manager.
   */
  public function __construct(?GiftcardOrderManager $giftcardOrderManager) {
    $this->giftcardOrderManager = $giftcardOrderManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      'commerce_klarna_payments.session_create' => [['addGiftcardRedemptionAsOrderItem']],
      'commerce_klarna_payments.order_create' => [['addGiftcardRedemptionAsOrderItem']],
    ];
  }

  /**
   * Add gift card redemption adjustments as an order item.
   *
   * @param \Drupal\commerce_klarna_payments\Event\RequestEvent $event
   *   Event.
   */
  public function addGiftCardRedemptionAsOrderItem(RequestEvent $event): void {
    $giftCardAdjustments = $this->getGiftcardAdjustments($event->getOrder());
    if ($giftCardAdjustments) {
      /** @var \Klarna\Payments\Model\Session $session */
      $session = $event->getData();
      $orderLines = $session->getOrderLines();
      $orderLines[] = $this->createGiftCardOrderLine($giftCardAdjustments);
      $session->setOrderLines($orderLines);
    }
  }

  /**
   * Get gift card adjustments for the order.
   *
   * @param \Drupal\commerce_order\Entity\OrderInterface $order
   *   Order.
   *
   * @return \Drupal\commerce_order\Adjustment[]
   *   Gift card adjustments.
   */
  public function getGiftcardAdjustments(OrderInterface $order): array {
    if ($this->giftcardOrderManager) {
      return $this->giftcardOrderManager->getAdjustments($order);
    }
    return [];
  }

  /**
   * Create a gift card order line item.
   *
   * @param \Drupal\commerce_order\Adjustment[] $giftCardAdjustments
   *   Gift card adjustments.
   *
   * @return \Klarna\Payments\Model\OrderLine
   *   Order line.
   */
  private function createGiftCardOrderLine(array $giftCardAdjustments): OrderLine {
    $commerceAmount = NULL;
    foreach ($giftCardAdjustments as $giftCardAdjustment) {
      if (!$commerceAmount) {
        $commerceAmount = $giftCardAdjustment->getAmount();
      }
      else {
        $commerceAmount = $commerceAmount->add($giftCardAdjustment->getAmount());
      }
    }
    $klarnaAmount = UnitConverter::toAmount($commerceAmount);
    return (new OrderLine())
      ->setName($this->t('Gift card redemption'))
      ->setQuantity(1)
      ->setUnitPrice($klarnaAmount)
      ->setTotalAmount($klarnaAmount);
  }

}

Remaining tasks

Create a merge request to include the above subscriber (in a suitable form) in the module.

User interface changes

None.

API changes

None.

Data model changes

None.

✨ Feature request
Status

Fixed

Version

3.0

Component

Code

Created by

🇨🇭Switzerland tcrawford

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024