NonProductionChargeBlocked
\Benecaster\Payment\NonProductionChargeBlocked
The exception OutboundChargeGuard throws when a money or subscription-lifecycle call is refused because this install is a copy of the one that armed itself. This is the thing your add-on catches at its own entry points.
Every entry point that can reach a guarded call must catch it, and the reason is specific. An uncaught exception inside a webhook handler is a 500, and Stripe answers a 500 by retrying — so the one thing worse than the charge you blocked is blocking it in a way that makes Stripe try again all day. Catch it at the boundary and convert it to a settled refusal.
It is a distinct type rather than a bare runtime exception so that boundaries can catch this without swallowing genuine Stripe or transport errors, which must keep propagating and being retried.
It extends RuntimeException deliberately, and the reason belongs in your catch ordering: every boundary that was already defensive degrades to its old behaviour instead of letting the refusal escape through it. If you catch both, the specific arm must come first — a RuntimeException arm placed above it will swallow the refusal and, worse, commonly echoes the caught message to the caller, publishing both site URLs and the wp-config.php constant.
This is also why the plugin throws here at all, where the license server’s equivalent rule says to return the method’s established failure value: the plugin’s money methods return a non-nullable subscription or payment intent and have no failure value to return, so their established failure mode already is an exception.
The exception carries three public readonly properties, set by the constructor: $operation (the operation name passed to OutboundChargeGuard::assert_may_move_money()), $captured_url (the site URL this install recorded when it armed itself, an empty string if none) and $current_url (the URL it is running at now). OutboundChargeGuard is the only thing in Benecaster that throws it, and you would not construct it yourself.
Methods
| Method | Visibility | Since | Description |
|---|---|---|---|
__construct( string $operation, string $captured_url, string $current_url ) |
Public | — | Stores the three values as public readonly properties and builds the exception message from them. The message names the operation, both URLs (an empty $captured_url is shown as (unrecorded)) and the BENECASTER_IS_PRODUCTION constant that disarms the guard. It sets no custom exception code. |
Notes
The three properties are for your logs, never for a response body.
The assembled message names both URLs and the constant that disarms the guard; that is infrastructure detail a subscriber can do nothing with, on endpoints an anonymous visitor can reach. Benecaster's own routes answer with a fixed generic string and send the detail to the debug log instead.