Event Monitoring
IntentChangeContext
The context object passed to every watcher callback. It carries metadata about the origin of the event.
interface IntentChangeContext {
local: boolean;
}
| Property | Type | Description |
|---|---|---|
local | boolean | true when the event was triggered by the current instance. false when it came from another cluster node. |
This distinction is useful in clustered deployments where multiple instances receive the same Stripe webhook. By filtering on context.local, you can ensure that side effects such as sending emails or updating a database execute only once.
IntentWatcher Callback Type
All watcher functions accept a callback that conforms to the following signature:
type IntentWatcher = (
id: string | undefined,
intent: Stripe.PaymentIntent,
context: IntentChangeContext,
) => void;
| Parameter | Type | Description |
|---|---|---|
id | string | undefined | The custom payload ID from metadata.payload, set during InitializePayment. |
intent | Stripe.PaymentIntent | The full payment intent object with its current state. |
context | IntentChangeContext | Event origin metadata. |
WatchAllPayments
Registers a callback that fires whenever any payment intent changes status. Use this for global side effects such as logging, analytics, or audit trails.
import { WatchAllPayments } from "@antelopejs/interface-stripe";
WatchAllPayments((id, intent, context) => {
console.log(`Payment ${id} changed to status: ${intent.status}`);
console.log(`Origin: ${context.local ? "local" : "remote"}`);
if (intent.status === "succeeded") {
// Handle successful payment
} else if (intent.status === "canceled") {
// Handle canceled payment
}
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | IntentWatcher | Yes | Function invoked on every payment intent change. |
onlyLocal | boolean | No | When true, the callback fires only for events originating locally. Defaults to false. |
Filtering Local Events
In a clustered deployment, set onlyLocal to true to prevent duplicate processing across instances.
import { WatchAllPayments } from "@antelopejs/interface-stripe";
// Only react to events from the current instance
WatchAllPayments((id, intent, context) => {
if (intent.status === "succeeded") {
sendConfirmationEmail(id);
}
}, true);
Tip: The
onlyLocalfilter applies before the callback is invoked. When set totrue, events from remote cluster nodes never reach the callback.
WatchPayment
Registers a callback for a specific payment intent. The callback fires whenever that payment intent changes status. Once the intent reaches a terminal state (succeeded or canceled), the watcher is automatically removed.
import { WatchPayment } from "@antelopejs/interface-stripe";
WatchPayment("pi_1234567890", (id, intent, context) => {
if (intent.status === "succeeded") {
console.log(`Payment ${id} completed successfully`);
updateOrderStatus(id, "paid");
} else if (intent.status === "canceled") {
console.log(`Payment ${id} was canceled: ${intent.cancellation_reason}`);
updateOrderStatus(id, "canceled");
} else {
console.log(`Payment ${id} status: ${intent.status}`);
}
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
paymentIntentId | string | Yes | The Stripe payment intent ID to monitor. |
callback | IntentWatcher | Yes | Function invoked when the intent changes state. |
Note: Unlike
WatchAllPayments, theWatchPaymentcallback does not support theonlyLocalfilter. It fires for both local and remote events.
Automatic Cleanup
When a payment intent reaches a terminal state (succeeded or canceled), the event system performs automatic cleanup:
- Per-intent watchers registered with
WatchPaymentare removed. - Pending promises from
WaitForPaymentare resolved or rejected.
This prevents memory leaks from watchers that are no longer needed.
Combine Watchers with Payment Processing
The following example creates a payment intent, watches for its completion, and returns the client secret for frontend confirmation.
import { InitializePayment, WatchPayment, WaitForPayment } from "@antelopejs/interface-stripe";
async function processAndMonitorPayment(orderId: string, amount: number) {
const intent = await InitializePayment(orderId, {
amount,
currency: "usd",
payment_method_types: ["card"],
});
// Option A: React to status changes with a callback
WatchPayment(intent.id, (id, updatedIntent, context) => {
if (updatedIntent.status === "succeeded") {
console.log(`Order ${id} has been paid`);
} else if (updatedIntent.status === "canceled") {
console.log(`Payment for order ${id} was canceled`);
}
});
// Option B: Await the terminal state with a promise
try {
const completed = await WaitForPayment(intent.id);
console.log(`Order ${orderId} payment confirmed`);
} catch (reason) {
console.error(`Order ${orderId} payment failed:`, reason);
}
return intent;
}
Important: You can use
WatchPaymentandWaitForPaymenton the same payment intent. Both mechanisms operate independently and are cleaned up automatically when the intent reaches a terminal state.