nordkit/svea
Modern PHP SDK for Svea Checkout, Payment Admin, webhook subscriptions and inbound webhook verification. Fluent API with typed value objects, retries, idempotency, async task polling, and a robust testing fake. Includes first-class Laravel integration.
Installation:
composer require nordkit/svea
php artisan vendor:publish --tag=svea-config # Laravel only
Add .env variables:
SVEA_MERCHANT_ID=your_merchant_id
SVEA_SHARED_SECRET=your_shared_secret
SVEA_ENVIRONMENT=test|production
SVEA_WEBHOOK_SECRET=your_webhook_secret
First Use Case: Create a checkout order in Laravel:
use Svea\Laravel\Svea;
$order = Svea::checkout()->create(new CheckoutOrder(
currency: 'SEK',
countryCode: 'SE',
clientOrderNumber: 'ORD-123',
// ... other required fields
));
Where to Look First:
config/svea.php for configuration details.src/Svea/Checkout/ for checkout-specific logic.Checkout Flow:
// Create order
$order = Svea::checkout()->create($checkoutOrder);
// Retrieve order snippet for frontend
$snippet = $order->snippet();
// Update order (e.g., add discount)
Svea::checkout()->order($order->id())
->update(fn ($order) => $order->discountPercent(1000));
Admin Operations:
// Deliver payment
Svea::admin()->order('12345678')
->withIdempotencyKey('unique-key')
->deliver();
// Cancel payment
Svea::admin()->order('12345678')
->cancel();
Webhook Handling:
// Inbound webhook (Laravel)
public function handleWebhook(Request $request) {
$event = Svea::webhook()->fromRequest($request);
// Process event (e.g., update order status)
}
Svea::checkout(), Svea::admin(), etc., for concise syntax.Svea::admin()->order('12345678')
->when($isPartial, fn($req) => $req->deliver(rows: $rowIds));
withIdempotencyKey() for retries in queues.TaskResponse on HTTP 202:
$task = Svea::admin()->order('12345678')->deliverAsync();
$response = $task->waitForCompletion();
Svea::fake()
->checkout()
->create(fn ($order) => $order->status('Final'));
// Assertions
Svea::assertCheckoutWasCreated(fn ($order) => $order->clientOrderNumber('ORD-123'));
Minor-Unit Values:
29900 for 299.00 SEK) causes API errors.Svea::minor(299) or 29900.Webhook Verification:
webhook_secret ≠ shared_secret. Use the former for inbound HMAC verification.SVEA_WEBHOOK_SECRET separately.Idempotency Keys:
withIdempotencyKey() for Admin operations.Retry Logic:
0. Enable with SVEA_MAX_RETRIES=3..env or via SveaClient constructor.Locale/Currency Mismatch:
countryCode/currency/locale trios (e.g., SEK + NO) fail silently.nordkit/wiretap to log requests/responses:
$stack->push(WiretapMiddleware::make(app(Wiretap::class)));
SveaApiException for API errors:
try {
Svea::admin()->order('123')->deliver();
} catch (SveaApiException $e) {
log::error($e->getStatusCode(), ['body' => $e->getBody()]);
}
Custom Middleware:
Add Guzzle middleware to SveaClient:
$client = new SveaClient([
'merchant_id' => 'abc',
// ...
], HandlerStack::create()->push(new CustomMiddleware()));
Event Decoupling:
Dispatch SveaWebhookReceived in Laravel to decouple handlers:
SveaWebhookReceived::dispatch($event);
Override Base URLs:
Configure SVEA_CHECKOUT_URL, SVEA_ADMIN_URL, or SVEA_SUBSCRIPTIONS_URL in .env for local testing.
bootstrap/providers.php.php artisan svea:subscription:add).withIdempotencyKey() to safely retry failed Admin operations.How can I help you explore Laravel packages today?