Add typed error handling, retries, and webhook receiver

- Typed exceptions: LeadMailException base with LeadMailRequestException
  (structured statusCode/errorCode/logId/validationErrors) and
  LeadMailConnectionException; sendEmail/getDomains now throw these instead
  of raw Guzzle exceptions, and a malformed body is no longer a silent null.
- Automatic retry with exponential backoff on idempotent calls
  (getDomains, verifyEmail); sends are never retried to avoid duplicates.
- Webhook receiver: auto-registered route + LeadMailWebhookController that
  verifies the HMAC signature, logs failures, and dispatches a
  LeadMailWebhookReceived event. WebhookSignature/WebhookEvent/LeadMailWebhook
  helpers for manual handling.
- Webhook self-registration client methods (registerWebhook/getWebhook/
  deleteWebhook) and a promptless `leadmail:install` command that registers
  the URL and writes LEADMAIL_WEBHOOK_SECRET to .env.
- Null-safe client binding when LEADMAIL_TOKEN is unset.
- Test suite (Pest + Testbench) covering all of the above.
This commit is contained in:
netlas
2026-06-09 11:14:10 +03:00
parent bf8aac48e6
commit b2b61a26ed
24 changed files with 1467 additions and 21 deletions

View File

@@ -52,4 +52,55 @@ return [
|
*/
'auto_tenant' => env('LEADMAIL_AUTO_TENANT', true),
/*
|--------------------------------------------------------------------------
| Retries
|--------------------------------------------------------------------------
|
| How many times to retry a request that fails transiently (connection
| errors and 429/5xx responses) before giving up. The delay between
| attempts grows exponentially from the base delay (in milliseconds).
|
*/
'retries' => env('LEADMAIL_RETRIES', 2),
'retry_delay' => env('LEADMAIL_RETRY_DELAY_MS', 200),
/*
|--------------------------------------------------------------------------
| Webhook Secret
|--------------------------------------------------------------------------
|
| The signing secret for verifying incoming failure webhooks. This must
| match the webhook secret shown for this client app in the leadMail admin
| dashboard. Set automatically by `php artisan leadmail:install`.
|
*/
'webhook_secret' => env('LEADMAIL_WEBHOOK_SECRET'),
/*
|--------------------------------------------------------------------------
| Webhook Route
|--------------------------------------------------------------------------
|
| The path the SDK automatically registers to receive failure webhooks.
| The registered endpoint verifies the signature, logs failures, and fires
| a LeadMailWebhookReceived event you can listen for. Set to null to
| disable auto-registration and handle the route yourself.
|
*/
'webhook_route' => env('LEADMAIL_WEBHOOK_ROUTE', '/webhooks/leadmail'),
/*
|--------------------------------------------------------------------------
| Webhook Route Middleware
|--------------------------------------------------------------------------
|
| Middleware applied to the auto-registered webhook route. The endpoint is
| already authenticated by HMAC signature, so it deliberately runs outside
| the "web" group (no CSRF, no session).
|
*/
'webhook_middleware' => ['throttle:60,1'],
];