Eventonomy

Recipe: Hook Into Checkout

Goal: Run code at three moments in the paid order lifecycle - before an order is created (to validate or modify), when an order is paid, and when an order is refunded.

Pro context: Checkout is a Pro feature. These hooks fire only when Eventonomy Pro is active and a paid ticket is purchased. On the Free plan, orders can exist as $0 records but no gateway payment hooks fire.

Seams Used

Seam Type When it fires
evnm_before_create_order Filter Before the order row is inserted. Return WP_Error to abort.
evnm_after_create_order Action After the order row is inserted (status is typically pending).
evnm_after_update_order Action When an order field changes - including the status flip to paid.
evnm_before_refund_order Filter Before a refund is issued. Return WP_Error to abort.
evnm_after_refund_order Action After the gateway refund() call succeeds.

Step 1 - Validate Before Creation

add_filter( 'evnm_before_create_order', function ( array $order, array $context ): array {
    // Block orders from a specific email domain.
    $email = (string) ( $order['email'] ?? '' );
    if ( str_ends_with( $email, '@blocked.example.com' ) ) {
        return new \WP_Error(
            'my_addon_blocked_email',
            __( 'Orders from this email domain are not accepted.', 'my-addon' ),
            [ 'status' => 422 ]
        );
    }
    return $order;
}, 10, 2 );

Step 2 - React When an Order Is Paid

The evnm_after_update_order action fires every time any order field changes. Check $changed_keys for 'status' and confirm the new status is 'paid':

add_action( 'evnm_after_update_order', function ( array $order, array $changed_keys, array $context ): void {
    if ( ! in_array( 'status', $changed_keys, true ) || 'paid' !== $order['status'] ) {
        return;
    }

    // Grant a perk for each ticket in the order.
    foreach ( $order['line_items'] as $line ) {
        my_addon_grant_perk( $order['user_id'], (int) $line['ticket_id'], (int) $line['quantity'] );
    }

    // Send to external CRM.
    my_addon_push_order_to_crm( $order );
}, 10, 3 );

$order contains the full order row including id, status, total, currency, user_id, event_id, and line_items.

Step 3 - React When an Order Is Refunded

add_action( 'evnm_after_refund_order', function ( array $order, int $refunded_cents, array $context ): void {
    my_addon_revoke_perk( $order['user_id'], $order['id'] );
    my_addon_log_refund( $order['id'], $refunded_cents, $order['currency'] );
}, 10, 3 );

The line_items Shape

// Each element in $order['line_items']:
[
    'ticket_id' => 42,
    'name'      => 'General Admission',
    'quantity'  => 2,
    'unit_price' => 2500,  // in minor units (cents)
    'total'      => 5000,
]

Prices are in the order's currency minor units (e.g. cents for USD). Use evnm_format_money() to convert to a display string.

Reading Order Data

Always resolve the order repository through the contract - never new a concrete:

$repo  = evnm( \Eventonomy\Contracts\OrderRepositoryInterface::class );
$order = $repo->get( $order_id );

Verify It Worked

  1. Create a test event with a paid ticket.
  2. Complete checkout using a Stripe test card (4242 4242 4242 4242).
  3. Check that your evnm_after_update_order callback fired: look in wp-content/debug.log or query your CRM/perk store.
  4. Issue a refund from the Stripe Dashboard and confirm evnm_after_refund_order fired.

Related