Issue:
feat(webhooks): allow manually retrying delivery of outgoing webhooks

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
This PR includes changes in the outgoing webhooks flow to allow manually retrying webhook deliveries, and adds an API endpoint for the same.


- URL: `/events/{merchant_id_or_profile_id}/{event_id}/retry`
- Authentication: Admin API authentication + JWT
- The endpoint must return the request and response information for the attempted retry.


### Additional Changes

- [x] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->

This PR adds a new endpoint to retry outgoing webhook delivery.

## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
This allows users to debug issues in case the delivery of webhooks to their application server fails, without having to wait for the application to automatically retry at set intervals.

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->

This PR adds a new endpoint and testing it is pretty straightforward. It can be tried out using a request like so:

```shell
curl -X POST -H 'api-key: {{admin_api_key}}' '{{baseUrl}}/events/{{merchant_id_or_profile_id}}/{{event_id}}/retry'
```

- In case of errors hitting the merchant server (say URL is inaccessible):

  ```shell
  curl -X POST -H 'api-key: test_admin' 'http://localhost:8080/events/pro_H7FbvX2pBuJLjlPhkpRa/evt_018e62ea2215731c915c3a47e4753e4a/retry' 2>/dev/null | jq '.'
  {
    "event_id": "evt_018e6581512d7b9bba60ec4ca44f364f",
    "merchant_id": "merchant_1710609960",
    "profile_id": "pro_H7FbvX2pBuJLjlPhkpRa",
    "object_id": "pay_6AMmb6rtlPDarBLlotAH",
    "event_type": "payment_succeeded",
    "event_class": "payments",
    "is_delivery_successful": false,
    "initial_attempt_id": "evt_018e48d5ad6c73d5a289342e6132b224",
    "created": "2024-03-22T09:32:37.550Z",
    "request": {
      "body": "{\"merchant_id\":\"merchant_1710609960\",\"event_id\":\"evt_018e48d5ad6c73d5a289342e6132b224\",\"event_type\":\"payment_succeeded\",\"content\":{\"type\":\"payment_details\",\"object\":{\"payment_id\":\"pay_6AMmb6rtlPDarBLlotAH\",\"merchant_id\":\"merchant_1710609960\",\"status\":\"succeeded\",\"amount\":6540,\"net_amount\":6540,\"amount_capturable\":0,\"amount_received\":6540,\"connector\":\"stripe\",\"client_secret\":\"pay_6AMmb6rtlPDarBLlotAH_secret_1hjI8KVOKf5xhMXBTwRj\",\"created\":\"2024-03-16T19:55:45.335Z\",\"currency\":\"USD\",\"customer_id\":\"StripeCustomer\",\"description\":\"Its my first payment request\",\"refunds\":null,\"disputes\":null,\"mandate_id\":null,\"mandate_data\":null,\"setup_future_usage\":null,\"off_session\":null,\"capture_on\":null,\"capture_method\":\"automatic\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"last4\":\"4242\",\"card_type\":null,\"card_network\":null,\"card_issuer\":null,\"card_issuing_country\":null,\"card_isin\":\"424242\",\"card_extended_bin\":\"42424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\"},\"billing\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null}},\"payment_token\":null,\"shipping\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null},\"billing\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null},\"order_details\":null,\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"return_url\":\"https://google.com/\",\"authentication_type\":\"no_three_ds\",\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"next_action\":null,\"cancellation_reason\":null,\"error_code\":null,\"error_message\":null,\"unified_code\":null,\"unified_message\":null,\"payment_experience\":null,\"payment_method_type\":\"credit\",\"connector_label\":null,\"business_country\":null,\"business_label\":\"default\",\"business_sub_label\":null,\"allowed_payment_method_types\":null,\"ephemeral_key\":{\"customer_id\":\"StripeCustomer\",\"created_at\":1710618945,\"expires\":1710622545,\"secret\":\"epk_5736317c91e04787838bd300d6f53877\"},\"manual_retry_allowed\":false,\"connector_transaction_id\":\"pi_3Ov3KXD5R7gDAGff1ZbtdptB\",\"frm_message\":null,\"metadata\":{\"udf1\":\"value1\",\"login_date\":\"2019-09-10T10:11:12Z\",\"new_customer\":\"true\"},\"connector_metadata\":null,\"feature_metadata\":null,\"reference_id\":\"pi_3Ov3KXD5R7gDAGff1ZbtdptB\",\"payment_link\":null,\"profile_id\":\"pro_H7FbvX2pBuJLjlPhkpRa\",\"surcharge_details\":null,\"attempt_count\":1,\"merchant_decision\":null,\"merchant_connector_id\":\"mca_qeS5H2fLkr8GLzN9SNWd\",\"incremental_authorization_allowed\":null,\"authorization_count\":null,\"incremental_authorizations\":null,\"external_authentication_details\":null,\"external_3ds_authentication_attempted\":false,\"expires_on\":\"2024-03-16T20:10:45.335Z\",\"fingerprint\":null,\"payment_method_id\":null,\"payment_method_status\":null}},\"timestamp\":\"2024-03-16T19:55:46.924Z\"}",
      "headers": [
        [
          "content-type",
          "application/json"
        ],
        [
          "X-Webhook-Signature-512",
          "68dd7abf747b5c33eaef5d7450990594aff5b260e79a33405539311f037efc2b70f86b062bcab9a231bd8fa8e8141df078e5834d52add7751da48247bf31ece5"
        ]
      ]
    },
    "response": {
      "body": null,
      "headers": null,
      "status_code": null,
      "error_message": "Unable to send request to merchant server"
    },
    "delivery_attempt": "manual_retry"
  }
  ```

  Note:

    - `initial_attempt_id` would not contain the `event_id` of the event being retried, but the `initial_attempt_id` of the event being retried. This would allow us to list all attempts including manual delivery attempts related to the initial attempt.
    - `delivery_attempt` is `manual_retry` in this case
    - `response.error_message` is non-null

- Successful delivery:

  ```shell
  curl -X POST -H 'api-key: test_admin' 'http://localhost:8080/events/pro_H7FbvX2pBuJLjlPhkpRa/evt_018e62ea2215731c915c3a47e4753e4a/retry' 2>/dev/null | jq '.'
  {
    "event_id": "evt_018e6589a52e75a9bb0dbb72fd6b6434",
    "merchant_id": "merchant_1710609960",
    "profile_id": "pro_H7FbvX2pBuJLjlPhkpRa",
    "object_id": "pay_6AMmb6rtlPDarBLlotAH",
    "event_type": "payment_succeeded",
    "event_class": "payments",
    "is_delivery_successful": true,
    "initial_attempt_id": "evt_018e48d5ad6c73d5a289342e6132b224",
    "created": "2024-03-22T09:41:43.342Z",
    "request": {
      "body": "{\"merchant_id\":\"merchant_1710609960\",\"event_id\":\"evt_018e48d5ad6c73d5a289342e6132b224\",\"event_type\":\"payment_succeeded\",\"content\":{\"type\":\"payment_details\",\"object\":{\"payment_id\":\"pay_6AMmb6rtlPDarBLlotAH\",\"merchant_id\":\"merchant_1710609960\",\"status\":\"succeeded\",\"amount\":6540,\"net_amount\":6540,\"amount_capturable\":0,\"amount_received\":6540,\"connector\":\"stripe\",\"client_secret\":\"pay_6AMmb6rtlPDarBLlotAH_secret_1hjI8KVOKf5xhMXBTwRj\",\"created\":\"2024-03-16T19:55:45.335Z\",\"currency\":\"USD\",\"customer_id\":\"StripeCustomer\",\"description\":\"Its my first payment request\",\"refunds\":null,\"disputes\":null,\"mandate_id\":null,\"mandate_data\":null,\"setup_future_usage\":null,\"off_session\":null,\"capture_on\":null,\"capture_method\":\"automatic\",\"payment_method\":\"card\",\"payment_method_data\":{\"card\":{\"last4\":\"4242\",\"card_type\":null,\"card_network\":null,\"card_issuer\":null,\"card_issuing_country\":null,\"card_isin\":\"424242\",\"card_extended_bin\":\"42424242\",\"card_exp_month\":\"10\",\"card_exp_year\":\"25\",\"card_holder_name\":\"joseph Doe\"},\"billing\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null}},\"payment_token\":null,\"shipping\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null},\"billing\":{\"address\":{\"city\":\"San Fransico\",\"country\":\"US\",\"line1\":\"1467\",\"line2\":\"Harrison Street\",\"line3\":\"Harrison Street\",\"zip\":\"94122\",\"state\":\"California\",\"first_name\":\"joseph\",\"last_name\":\"Doe\"},\"phone\":{\"number\":\"8056594427\",\"country_code\":\"+91\"},\"email\":null},\"order_details\":null,\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"return_url\":\"https://google.com/\",\"authentication_type\":\"no_three_ds\",\"statement_descriptor_name\":\"joseph\",\"statement_descriptor_suffix\":\"JS\",\"next_action\":null,\"cancellation_reason\":null,\"error_code\":null,\"error_message\":null,\"unified_code\":null,\"unified_message\":null,\"payment_experience\":null,\"payment_method_type\":\"credit\",\"connector_label\":null,\"business_country\":null,\"business_label\":\"default\",\"business_sub_label\":null,\"allowed_payment_method_types\":null,\"ephemeral_key\":{\"customer_id\":\"StripeCustomer\",\"created_at\":1710618945,\"expires\":1710622545,\"secret\":\"epk_5736317c91e04787838bd300d6f53877\"},\"manual_retry_allowed\":false,\"connector_transaction_id\":\"pi_3Ov3KXD5R7gDAGff1ZbtdptB\",\"frm_message\":null,\"metadata\":{\"udf1\":\"value1\",\"login_date\":\"2019-09-10T10:11:12Z\",\"new_customer\":\"true\"},\"connector_metadata\":null,\"feature_metadata\":null,\"reference_id\":\"pi_3Ov3KXD5R7gDAGff1ZbtdptB\",\"payment_link\":null,\"profile_id\":\"pro_H7FbvX2pBuJLjlPhkpRa\",\"surcharge_details\":null,\"attempt_count\":1,\"merchant_decision\":null,\"merchant_connector_id\":\"mca_qeS5H2fLkr8GLzN9SNWd\",\"incremental_authorization_allowed\":null,\"authorization_count\":null,\"incremental_authorizations\":null,\"external_authentication_details\":null,\"external_3ds_authentication_attempted\":false,\"expires_on\":\"2024-03-16T20:10:45.335Z\",\"fingerprint\":null,\"payment_method_id\":null,\"payment_method_status\":null}},\"timestamp\":\"2024-03-16T19:55:46.924Z\"}",
      "headers": [
        [
          "content-type",
          "application/json"
        ],
        [
          "X-Webhook-Signature-512",
          "68dd7abf747b5c33eaef5d7450990594aff5b260e79a33405539311f037efc2b70f86b062bcab9a231bd8fa8e8141df078e5834d52add7751da48247bf31ece5"
        ]
      ]
    },
    "response": {
      "body": "",
      "headers": [
        [
          "content-length",
          "0"
        ],
        [
          "date",
          "Fri, 22 Mar 2024 09:41:44 GMT"
        ],
        [
          "access-control-allow-origin",
          "*"
        ],
        [
          "set-cookie",
          "ARRAffinity=669b1a143e31fb4dd62d7cac87cd552f46ae1eaa9e19a1bc7e87014967e06b05;Path=/;HttpOnly;Secure;Domain=smee.io"
        ],
        [
          "set-cookie",
          "ARRAffinitySameSite=669b1a143e31fb4dd62d7cac87cd552f46ae1eaa9e19a1bc7e87014967e06b05;Path=/;HttpOnly;SameSite=None;Secure;Domain=smee.io"
        ],
        [
          "request-context",
          "appId=cid-v1:"
        ],
        [
          "x-powered-by",
          "Express"
        ]
      ],
      "status_code": 200,
      "error_message": null
    },
    "delivery_attempt": "manual_retry"
  }
  ```

- The above request should behave the same way by replacing the profile ID with the merchant ID, or replacing the `api-key` header and value with the JWT token received after user sign in.

## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable


Resolution:
<think>
PR Context:
- Title: refactor(webhook_events): allow listing unique webhook events based on profile ID
- Merged: 2024-08-14T09:51:26Z
- Files changed: 15 files
- Commits: 3 commits

Implementation approach:
## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [x] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->

This PR adds back a feature that was removed in #5566: the ability to list unique webhook events by profile ID. This is done by accepting `profile_id` as a query parameter in the Events List endpoint. As for the other two webhook endpoints (
</think>

To implement this, you'll need to modify:


**Detailed Implementation:**


**Commit 1:** refactor(webhook_events): allow listing unique webhook events based on profile ID (#5598)
Files to modify:


**crates/api_models/src/webhook_events.rs**
  Modify existing code

**crates/common_utils/src/events.rs**
  Modify existing code

**crates/diesel_models/src/query/business_profile.rs**
  Add:
    - function: pub::find_by_merchant_id_profile_id

**crates/openapi/src/routes/webhook_events.rs**
  Modify existing code

**crates/router/src/core/webhooks/webhook_events.rs**
  Modify existing code

**crates/router/src/db/business_profile.rs**
  Add:
    - function: private::find_business_profile_by_merchant_id_profile_id
    - function: private::find_business_profile_by_merchant_id_profile_id

**crates/router/src/db/events.rs**
  Remove:
    - function: private::list_events_by_profile_id_initial_attempt_id
    - function: private::list_events_by_profile_id_initial_attempt_id

**crates/router/src/db/kafka_store.rs**
  Remove:
    - function: private::list_events_by_profile_id_initial_attempt_id
  Add:
    - function: private::find_business_profile_by_merchant_id_profile_id

**crates/router/src/routes/app.rs**
  Modify existing code

**crates/router/src/routes/webhook_events.rs**
  Modify existing code

**crates/router/src/services/authentication.rs**
  Modify existing code