text: class AdyenSubscriber {
    constructor(container) {
      /** @private @const {CartService} */
      this.cartService_ = container.cartService
  
      /** @private @const {OrderService} */
      this.orderService_ = container.orderService
  
      /** @private @const {EventBusService} */
      this.eventBus_ = container.eventBusService
  
      /** @private @const {PaymentRepository} */
      this.paymentRepository_ = container.paymentRepository
  
      this.manager_ = container.manager
  
      this.eventBus_.subscribe(
        "adyen.notification_received",
        async (notification) => this.handleAdyenNotification(notification)
      )
    }
  
    /**
     * Webhook handler for Adyen payment.
     * @param {object} notification - webhook notification object
     * @returns {string} the status of the payment intent
     */
    async handleAdyenNotification(notification) {
      switch (true) {
        case notification.success === "true" &&
          notification.eventCode === "AUTHORISATION": {
          this.handleAuthorization_(notification)
          break
        }
        case notification.success === "false" &&
          notification.eventCode === "AUTHORISATION": {
          this.handleFailedAuthorization_(notification)
          break
        }
        case notification.success === "true" &&
          notification.eventCode === "CAPTURE_FAILED": {
          this.handleFailedCapture_(notification)
          break
        }
        case notification.success === "false" &&
          notification.eventCode === "CAPTURE": {
          this.handleFailedCapture_(notification)
          break
        }
        case notification.success === "false" &&
          notification.eventCode === "REFUND": {
          this.handleFailedRefund_(notification)
          break
        }
        default:
          break
      }
    }
  
    async handleFailedAuthorization_(notification) {
      const cartId = notification.additionalData["metadata.cart_id"]
      const cart = await this.cartService_.retrieve(cartId, {
        relations: ["payment_sessions"],
      })
  
      const { payment_session } = cart
  
      const updated = {
        ...payment_session,
        status: "error",
        data: {
          ...payment_session.data,
          pspReference: notification.pspReference,
        },
      }
  
      await this.cartService_.updatePaymentSession(cart.id, updated)
    }
  
    async handleAuthorization_(notification) {
      const cartId = notification.additionalData["metadata.cart_id"]
      const paymentRepository = this.manager_.getCustomRepository(
        this.paymentRepository_
      )
  
      // We need to ensure, that an order is created in situations, where the
      // customer might have closed their browser prior to order creation
      try {
        const orderPayment = await paymentRepository.findOne({
          where: { cart_id: cartId },
        })
  
        if (!orderPayment) {
          throw new Error("Payment not found")
        }
  
        const updatedPayment = {
          ...orderPayment,
          data: {
            ...orderPayment.data,
            resultCode: "Authorised",
            pspReference: notification.pspReference,
          },
        }
  
        await this.paymentRepository_.save(updatedPayment)
      } catch (error) {
        await this.manager_.transaction(async (manager) => {
          const session = {
            pspReference: notification.pspReference,
            resultCode: "Authorised",
          }
  
          await this.cartService_
            .withTransaction(manager)
            .updatePaymentSession(cartId, session)
  
          await this.cartService_
            .withTransaction(manager)
            .authorizePayment(cartId)
  
          await this.orderService_.withTransaction(manager).createFromCart(cartId)
        })
      }
    }
  
    async handleFailedCapture_(notification) {
      const cartId = notification.additionalData["metadata.cart_id"]
  
      const order = await this.orderService_.retrieveByCartId(cartId)
  
      await this.orderService_.update(order.id, {
        payment_status: "requires_action",
      })
  
      await this.eventBus_.emit("order.payment_capture_failed", {
        order,
        error: new Error(`Adyen payment capture: ${notification.reason}`),
      })
    }
  
    async handleFailedRefund_(notification) {
      const cartId = notification.additionalData["metadata.cart_id"]
  
      const order = await this.orderService_.retrieveByCartId(cartId)
  
      await this.orderService_.update(order.id, {
        payment_status: "requires_action",
      })
  
      await this.eventBus_.emit("order.refund_failed", {
        order,
        error: new Error(`Adyen payment capture: ${notification.reason}`),
      })
    }
  }
  
  export default AdyenSubscriber
  