klarna/checkout
Deprecated Klarna Checkout PHP library/SDK for integrating Klarna Checkout. This package is no longer supported; use the maintained replacement klarna/kco_rest_php instead. Documentation and examples available at developers.klarna.com.
Installation:
composer require klarna/checkout
Note: Despite being archived, this remains the quickest way to integrate Klarna’s API in Laravel.
Configuration:
Add Klarna credentials to .env:
KLARNA_CLIENT_ID=your_client_id
KLARNA_CLIENT_SECRET=your_client_secret
KLARNA_BASE_URL=https://api.klarna.com
KLARNA_WEBHOOK_URL=https://your-app.com/klarna/webhook
Service Provider:
Register the Klarna client in AppServiceProvider.php:
public function boot()
{
$this->app->singleton('klarna', function ($app) {
return new \Klarna\Checkout($app['config']['klarna.client_id'], $app['config']['klarna.client_secret']);
});
}
First Use Case: Create a checkout session in a controller:
use Klarna\Checkout;
public function checkout(Request $request, Checkout $klarna)
{
$order = $klarna->createOrder([
'purchase_country' => 'SE',
'purchase_currency' => 'SEK',
'lines' => [
['type' => 'physical', 'reference' => 'order_123', 'quantity' => 1, 'unit_price' => 1000, 'tax_rate' => 25, 'total_amount' => 1250, 'total_tax_amount' => 250, 'discount_rate' => 0, 'type' => 'physical']
],
'merchant_urls' => [
'terms' => 'https://your-app.com/terms',
'checkout' => 'https://your-app.com/checkout',
],
]);
return redirect($order->checkout_url);
}
Webhook Endpoint: Add a route and handler for Klarna webhooks:
Route::post('/klarna/webhook', [KlarnaWebhookController::class, 'handle']);
createOrder() to generate a Klarna order with product lines, taxes, and merchant URLs.order_id in the session or database to track the checkout process.checkout_url returned by Klarna.$order = $klarna->createOrder($orderData);
session()->put('klarna_order_id', $order->order_id);
return redirect($order->checkout_url);
payment.authorized) to Laravel events or queue jobs.public function handle(Request $request, Checkout $klarna)
{
$payload = $request->getContent();
$signature = $request->header('Klarna-Signature');
if (!$klarna->verifyWebhook($payload, $signature)) {
abort(401);
}
$event = json_decode($payload, true);
// Dispatch event or process asynchronously
HandleKlarnaWebhookJob::dispatch($event);
}
captureOrder() to finalize authorized payments.createRefund() for partial or full refunds.$klarna->captureOrder($orderId, ['amount' => 1250]);
$refund = $klarna->createRefund($orderId, ['amount' => 500]);
$order = $klarna->getOrder($orderId);
if ($order->status === 'checked_out') {
// Update local database
}
recurring in the order lines.payment.pending webhooks to trigger subscription activation.'lines' => [
[
'type' => 'physical',
'reference' => 'subscription_123',
'quantity' => 1,
'unit_price' => 999,
'tax_rate' => 20,
'total_amount' => 1198.8,
'total_tax_amount' => 198.8,
'type' => 'physical',
'recurring' => [
'interval' => 'month',
'interval_unit' => 'month',
'max_intervals' => 12,
],
],
],
purchase_currency based on user location.$currency = $user->preferred_currency ?? 'SEK';
$order = $klarna->createOrder([
'purchase_country' => $user->country,
'purchase_currency' => $currency,
// ...
]);
Service Container: Bind the Klarna client to an interface for easier testing/mocking:
$this->app->bind(
KlarnaCheckoutInterface::class,
function ($app) {
return new \Klarna\Checkout($app['config']['klarna.client_id'], $app['config']['klarna.client_secret']);
}
);
Middleware for Auth: Protect Klarna-related routes with middleware to validate API tokens:
Route::middleware(['klarna.auth'])->group(function () {
Route::post('/klarna/webhook', [KlarnaWebhookController::class, 'handle']);
});
Queue Jobs for Webhooks: Offload webhook processing to a queue to avoid long-running requests:
public function handle(Request $request)
{
$payload = $request->getContent();
ProcessKlarnaWebhookJob::dispatch($payload);
return response()->json(['status' => 'queued']);
}
Database Reconciliation:
Store Klarna order_id and payment_id in your local database to sync statuses:
// Migration
Schema::create('klarna_orders', function (Blueprint $table) {
$table->id();
$table->string('klarna_order_id')->unique();
$table->string('status')->nullable();
$table->foreignId('user_id')->constrained();
$table->timestamps();
});
Event Dispatching: Trigger Laravel events for Klarna webhooks to decouple business logic:
event(new KlarnaPaymentAuthorized($eventData));
Deprecated Package:
Webhook Signature Verification:
Klarna-Signature header to prevent spoofing attacks.$expectedSignature = hash_hmac('sha256', $payload, $app['config']['klarna.secret']);
if (!hash_equals($expectedSignature, $signature)) {
abort(401, 'Invalid webhook signature');
}
Rate Limiting:
Illuminate\Cache\RateLimiter.Idempotency:
Currency and Country Restrictions:
Order Reference Uniqueness:
reference field in order lines must be unique per merchant. Reusing references may cause conflicts.Webhook Retries:
PCI Compliance:
How can I help you explore Laravel packages today?