Skip to content
Open
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
78 changes: 78 additions & 0 deletions src/ConvertKit_API_Traits.php
Original file line number Diff line number Diff line change
Expand Up @@ -2593,6 +2593,84 @@ public function revoke_webhook_endpoint_previous_secret(int $id)
return $this->post(sprintf('webhook_endpoints/%s/revoke_previous_secret', $id));
}

/**
* List deliveries for a webhook endpoint.
*
* Delivery history is retained for 30 days.
*
* @param integer $id Webhook Endpoint ID.
* @param string $status Delivery status (pending|delivered|failed|retrying).
* @param string $event_type Event type e.g. subscriber.created.
* @param string $after_cursor Return results after the given pagination cursor.
* @param string $before_cursor Return results before the given pagination cursor.
* @param integer $per_page Number of results to return.
*
* @since 2.9.0
*
* @see https://developers.kit.com/api-reference/webhooks/list-webhook-deliveries
*
* @return false|mixed
*/
public function get_webhook_endpoint_deliveries(
int $id,
string $status = '',
string $event_type = '',
string $after_cursor = '',
string $before_cursor = '',
int $per_page = 100
) {
// Build parameters.
$options = [];

if (!empty($status)) {
$options['status'] = $status;
}
if (!empty($event_type)) {
$options['event_type'] = $event_type;
}

// Send request.
return $this->get(
sprintf('webhook_endpoints/%s/deliveries', $id),
$this->build_total_count_and_pagination_params(
params: $options,
after_cursor: $after_cursor,
before_cursor: $before_cursor,
per_page: $per_page
)
);
}

/**
* Get a delivery for a webhook endpoint, including each delivery attempt.
*
* @param integer $id Webhook Endpoint ID.
* @param integer $delivery_id Delivery ID.
* @param boolean $include_payload Include the events sent in the delivery.
*
* @since 2.9.0
*
* @see https://developers.kit.com/api-reference/webhooks/get-webhook-delivery-details
*
* @return mixed|object
*/
public function get_webhook_endpoint_delivery(int $id, int $delivery_id, bool $include_payload = false)
{
// Build parameters.
$options = [];

// The API only accepts the strings true or false for this parameter.
if ($include_payload) {
$options['include_payload'] = 'true';
}

// Send request.
return $this->get(
sprintf('webhook_endpoints/%s/deliveries/%s', $id, $delivery_id),
$options
);
}

/**
* Verify the signature of a webhook endpoint delivery.
*
Expand Down
187 changes: 187 additions & 0 deletions tests/TestsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -6754,6 +6754,193 @@ public function testRevokeWebhookEndpointPreviousSecret()
$this->assertArrayNotHasKey('secret', $webhook_endpoint);
}

/**
* Test that get_webhook_endpoint_deliveries() returns the expected data.
*
* @since 2.9.0
*
* @return void
*/
public function testGetWebhookEndpointDeliveries()
{
// Create a webhook endpoint first.
$result = $this->api->create_webhook_endpoint(
url: 'https://webhook.site/' . str_shuffle('wfervdrtgsdewrafvwefds'),
events: ['subscriber.created']
);
$id = $result->webhook_endpoint->id;

// Set webhook_endpoint_ids to ensure webhook endpoints are deleted after test.
$this->webhook_endpoint_ids = [ $id ];

// Get deliveries.
$result = $this->api->get_webhook_endpoint_deliveries($id);

// Assert deliveries and pagination exist.
$this->assertDataExists($result, 'deliveries');
$this->assertPaginationExists($result);
}

/**
* Test that get_webhook_endpoint_deliveries() returns the expected data
* when a status is specified.
*
* @since 2.9.0
*
* @return void
*/
public function testGetWebhookEndpointDeliveriesWithStatus()
{
// Create a webhook endpoint first.
$result = $this->api->create_webhook_endpoint(
url: 'https://webhook.site/' . str_shuffle('wfervdrtgsdewrafvwefds'),
events: ['subscriber.created']
);
$id = $result->webhook_endpoint->id;

// Set webhook_endpoint_ids to ensure webhook endpoints are deleted after test.
$this->webhook_endpoint_ids = [ $id ];

// Get failed deliveries.
$result = $this->api->get_webhook_endpoint_deliveries(
id: $id,
status: 'failed'
);

// Assert deliveries and pagination exist.
$this->assertDataExists($result, 'deliveries');
$this->assertPaginationExists($result);

// Assert only failed deliveries were returned.
foreach ($result->deliveries as $delivery) {
$this->assertEquals('failed', $delivery->status);
}
}

/**
* Test that get_webhook_endpoint_deliveries() throws a ClientException when an invalid
* webhook endpoint ID is specified.
*
* @since 2.9.0
*
* @return void
*/
public function testGetWebhookEndpointDeliveriesWithInvalidID()
{
$this->assertApiError(
function () {
return $this->api->get_webhook_endpoint_deliveries(12345);
}
);
}

/**
* Test that get_webhook_endpoint_deliveries() and get_webhook_endpoint_delivery()
* return the expected data once a delivery has been made to the webhook endpoint.
*
* @since 2.9.0
*
* @return void
*/
public function testGetWebhookEndpointDelivery()
{
// Create a webhook endpoint first.
$result = $this->api->create_webhook_endpoint(
url: 'https://webhook.site/' . str_shuffle('wfervdrtgsdewrafvwefds'),
events: ['subscriber.created']
);
$id = $result->webhook_endpoint->id;

// Set webhook_endpoint_ids to ensure webhook endpoints are deleted after test.
$this->webhook_endpoint_ids = [ $id ];

// Create a subscriber, which triggers a delivery to the webhook endpoint.
$result = $this->api->create_subscriber(
email_address: $this->generateEmailAddress()
);

// Set subscriber_ids to ensure subscriber is unsubscribed after test.
$this->subscriber_ids = [ $result->subscriber->id ];

// Wait for the delivery to be made, as deliveries are sent asynchronously.
$delivery = $this->retryUntil(
function () use ($id) {
$result = $this->api->get_webhook_endpoint_deliveries(
id: $id,
event_type: 'subscriber.created'
);

return count($result->deliveries) ? $result->deliveries[0] : false;
}
);
$this->assertNotFalse($delivery, 'No delivery was made to the webhook endpoint in time.');
$delivery_id = $delivery->id;

// Confirm filtering by an event type the webhook endpoint isn't subscribed to returns no deliveries.
$result = $this->api->get_webhook_endpoint_deliveries(
id: $id,
event_type: 'tag.created'
);
$this->assertCount(0, $result->deliveries);

// Get the delivery.
$result = $this->api->get_webhook_endpoint_delivery(
id: $id,
delivery_id: $delivery_id
);

// Confirm the delivery and its attempts are returned, without the payload.
$delivery = get_object_vars($result->delivery);
$this->assertEquals($delivery_id, $delivery['id']);
$this->assertEquals('subscriber.created', $delivery['event_type']);
$this->assertArrayHasKey('attempts', $delivery);
$this->assertIsArray($delivery['attempts']);
$this->assertArrayNotHasKey('payload', $delivery);

// Get the delivery, including the payload.
$result = $this->api->get_webhook_endpoint_delivery(
id: $id,
delivery_id: $delivery_id,
include_payload: true
);

// Confirm the events sent in the delivery are returned.
$delivery = get_object_vars($result->delivery);
$this->assertArrayHasKey('payload', $delivery);
$this->assertIsArray($delivery['payload']);
$this->assertEquals('subscriber.created', $delivery['payload'][0]->type);
}

/**
* Test that get_webhook_endpoint_delivery() throws a ClientException when an invalid
* delivery ID is specified.
*
* @since 2.9.0
*
* @return void
*/
public function testGetWebhookEndpointDeliveryWithInvalidID()
{
// Create a webhook endpoint first.
$result = $this->api->create_webhook_endpoint(
url: 'https://webhook.site/' . str_shuffle('wfervdrtgsdewrafvwefds'),
events: ['subscriber.created']
);
$id = $result->webhook_endpoint->id;

// Set webhook_endpoint_ids to ensure webhook endpoints are deleted after test.
$this->webhook_endpoint_ids = [ $id ];

$this->assertApiError(
function () use ($id) {
return $this->api->get_webhook_endpoint_delivery(
id: $id,
delivery_id: 12345
);
}
);
}

/**
* Test that verify_webhook_signature() returns true when the signature is valid.
*
Expand Down
Loading