Repository: juspay/hyperswitch
File: crates/hyperswitch_connectors/src/connectors/worldpayxml.rs (Rust)

Code before:
    }

    fn get_webhook_object_reference_id(
        &self,
        #[cfg(feature = "payouts")] request: &webhooks::IncomingWebhookRequestDetails<'_>,
        #[cfg(not(feature = "payouts"))] _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        #[cfg(feature = "payouts")]
        {
            let body: worldpayxml::WorldpayXmlWebhookBody =
                utils::deserialize_xml_to_struct(request.body)?;
            Ok(api_models::webhooks::ObjectReferenceId::PayoutId(
                api_models::webhooks::PayoutIdType::ConnectorPayoutId(
                    body.notify.order_status_event.order_code,
                ),
            ))
        }
        #[cfg(not(feature = "payouts"))]
        {
            Err(report!(errors::ConnectorError::WebhooksNotImplemented))
        }
    }

    fn get_webhook_event_type(
        &self,
        #[cfg(feature = "payouts")] request: &webhooks::IncomingWebhookRequestDetails<'_>,
        #[cfg(not(feature = "payouts"))] _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        #[cfg(feature = "payouts")]
        {
            let body: worldpayxml::WorldpayXmlWebhookBody =
                utils::deserialize_xml_to_struct(request.body)?;
            Ok(worldpayxml::get_payout_webhook_event(
                body.notify.order_status_event.payment.last_event,
            ))
        }
        #[cfg(not(feature = "payouts"))]
        {
            Err(report!(errors::ConnectorError::WebhooksNotImplemented))
        }
    }

    fn get_webhook_resource_object(
        &self,
        #[cfg(feature = "payouts")] request: &webhooks::IncomingWebhookRequestDetails<'_>,
        #[cfg(not(feature = "payouts"))] _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        #[cfg(feature = "payouts")]
        {
            let body: worldpayxml::WorldpayXmlWebhookBody =
                utils::deserialize_xml_to_struct(request.body)?;

Review comment (suggestion):
refund and payout have some common events, if a payout webhook with those event arrives, it will be marked at refund events since is_refund_event function is getting executed first. 
Can we add the payout prefix check before checking for events to avoid such cases

Code after:
}

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Worldpayxml {
    async fn verify_webhook_source(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: common_utils::crypto::Encryptable<
            masking::Secret<serde_json::Value>,
        >,
        _connector_label: &str,
    ) -> CustomResult<bool, errors::ConnectorError> {
        // Bypass Source Verification since it is done via MTLS
        Ok(true)
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let body: worldpayxml::WorldpayXmlWebhookBody =
            utils::deserialize_xml_to_struct(request.body)?;
        let order_code = body.notify.order_status_event.order_code.clone();
        if worldpayxml::is_refund_event(body.notify.order_status_event.payment.last_event)
            && !order_code.starts_with("payout_")
        {
            return Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                api_models::webhooks::RefundIdType::ConnectorRefundId(order_code),
            ));
        }
        if worldpayxml::is_transaction_event(body.notify.order_status_event.payment.last_event) {
            return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(order_code),
            ));
        }
        #[cfg(feature = "payouts")]
        if order_code.starts_with("payout_") {
            return Ok(api_models::webhooks::ObjectReferenceId::PayoutId(
                api_models::webhooks::PayoutIdType::ConnectorPayoutId(order_code),
            ));
        }
        Err(report!(errors::ConnectorError::WebhookReferenceIdNotFound))
    }

    fn get_webhook_event_type(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        let body: worldpayxml::WorldpayXmlWebhookBody =