Skip to content

Commit bc0c941

Browse files
committed
Add webhook push support
1 parent 5c6916e commit bc0c941

File tree

4 files changed

+95
-1
lines changed

4 files changed

+95
-1
lines changed

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,71 @@ The Terminal class throws `\Exception` on failures. Common scenarios include:
276276

277277
Always wrap Terminal method calls in try-catch blocks for proper error handling.
278278

279+
## Webhook Push Notifications
280+
281+
When a payment succeeds, this package can automatically send a webhook to an external system (e.g. a financial tracking service). This uses [spatie/laravel-webhook-server](https://github.com/spatie/laravel-webhook-server) under the hood.
282+
283+
### Setup
284+
285+
1. Install the webhook server package:
286+
287+
```bash
288+
composer require spatie/laravel-webhook-server
289+
```
290+
291+
2. Set the webhook URL and signing secret in your `.env`:
292+
293+
```env
294+
LARAVEL_MULTIPAY_WEBHOOK_URL=https://your-receiving-app.com/api/webhooks/payments
295+
LARAVEL_MULTIPAY_WEBHOOK_SIGNING_SECRET=your-shared-secret
296+
```
297+
298+
3. Create a class that implements `Damms005\LaravelMultipay\Contracts\WebhookPayloadPackager`:
299+
300+
```php
301+
use Damms005\LaravelMultipay\Models\Payment;
302+
use Damms005\LaravelMultipay\Contracts\WebhookPayloadPackager;
303+
304+
class MyWebhookPayloadPackager implements WebhookPayloadPackager
305+
{
306+
public function getWebhookPayload(Payment $payment): array
307+
{
308+
return [
309+
'transaction_reference' => $payment->transaction_reference,
310+
'amount_paid' => $payment->original_amount_displayed_to_user,
311+
'payment_processor_name' => $payment->payment_processor_name,
312+
// ...add any app-specific data you need
313+
];
314+
}
315+
}
316+
```
317+
318+
4. Register your packager in a service provider:
319+
320+
```php
321+
config()->set(
322+
'laravel-multipay.webhook.payload_packager',
323+
\App\Services\MyWebhookPayloadPackager::class,
324+
);
325+
```
326+
327+
Once configured, every `SuccessfulLaravelMultipayPaymentEvent` will trigger a signed webhook POST to the configured URL with the payload returned by your packager.
328+
329+
### Backfilling Existing Payments
330+
331+
To send existing successful payments to the webhook endpoint:
332+
333+
```bash
334+
php artisan multipay:send-payments-webhook
335+
```
336+
337+
Options:
338+
- `--from=YYYY-MM-DD` — only payments created on or after this date
339+
- `--to=YYYY-MM-DD` — only payments created on or before this date
340+
- `--chunk=100` — number of payments per batch (default: 100)
341+
342+
The command fail-fast aborts after 3 consecutive batch failures.
343+
279344
## Testing
280345

281346
```bash
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
public function up(): void
10+
{
11+
$prefix = config('laravel-multipay.table_prefix', '');
12+
13+
Schema::table("{$prefix}payments", function (Blueprint $table) {
14+
$table->timestamp('webhook_dispatched_at')->nullable()->after('deleted_at');
15+
});
16+
}
17+
18+
public function down(): void
19+
{
20+
$prefix = config('laravel-multipay.table_prefix', '');
21+
22+
Schema::table("{$prefix}payments", function (Blueprint $table) {
23+
$table->dropColumn('webhook_dispatched_at');
24+
});
25+
}
26+
};

src/Commands/SendExistingPaymentsToWebhook.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function handle(): int
4343
return self::FAILURE;
4444
}
4545

46-
$query = Payment::successful();
46+
$query = Payment::successful()->whereNull('webhook_dispatched_at');
4747

4848
if ($from = $this->option('from')) {
4949
$query->where('created_at', '>=', $from);
@@ -76,6 +76,7 @@ public function handle(): int
7676
->useSecret($signingSecret)
7777
->dispatch();
7878

79+
Payment::whereIn('id', $payments->pluck('id'))->update(['webhook_dispatched_at' => now()]);
7980
$this->sentCount += $payments->count();
8081
$this->consecutiveFailures = 0;
8182
} catch (\Exception $e) {

src/Listeners/SendPaymentWebhookListener.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public function handle(SuccessfulLaravelMultipayPaymentEvent $event): void
2929
->payload($payload)
3030
->useSecret(config('laravel-multipay.webhook.signing_secret'))
3131
->dispatch();
32+
33+
$event->payment->update(['webhook_dispatched_at' => now()]);
3234
}
3335

3436
public static function buildPayload(Payment $payment): ?array

0 commit comments

Comments
 (0)