A comprehensive PHP SDK for integrating with Klarna's REST APIs. This package provides a clean, intuitive interface for all major Klarna services including Payments, Orders, Checkouts, and Customer Token management.
- Complete API Coverage: Support for Payments, Orders, Checkouts, and Customer Tokens APIs
- Multi-Region Support: Works with EU, North America (NA), and Oceania (OC) regions
- Environment Flexibility: Easy switching between test (playground) and live environments
- Type-Safe: Built with proper PHP typing and comprehensive error handling
- Developer Friendly: Intuitive method names and comprehensive documentation
- PSR-4 Compliant: Follows PHP-FIG standards for autoloading
- Modern PHP: Requires PHP 8.0+ with latest dependencies
- PHP 8.0 or higher
- Guzzle HTTP Client 6.5+ or 7.1+
- Carbon 2.40+ for date handling
- Valid Klarna API credentials
Before using this SDK, you need to obtain API credentials from Klarna:
- For Testing: Sign up for a Klarna Playground account
- For Production: Contact Klarna to get live API credentials
Klarna uses HTTP Basic Authentication with:
- Username: Your Klarna API username (UID)
- Password: Your Klarna API password
The SDK automatically sets these headers:
Authorization: Basic {base64(username:password)}
Accept: application/json
Content-Type: application/json
| Region | Code | Test Base URL | Live Base URL |
|---|---|---|---|
| Europe | EU |
https://api.playground.klarna.com/ |
https://api.klarna.com/ |
| North America | NA |
https://api-na.playground.klarna.com/ |
https://api-na.klarna.com/ |
| Oceania | OC |
https://api-oc.playground.klarna.com/ |
https://api-oc.klarna.com/ |
Install the package via Composer:
composer require vrajroham/php-klarna<?php
use Vrajroham\PhpKlarna\PhpKlarna;
// Initialize for EU region in test mode
$klarna = new PhpKlarna(
'your-api-username',
'your-api-password',
'EU', // Region: EU, NA, or OC
'test' // Mode: test or live
);
// For production (live mode)
$klarna = new PhpKlarna(
'your-live-username',
'your-live-password',
'EU',
'live'
);Create a .env file:
KLARNA_USERNAME=your-api-username
KLARNA_PASSWORD=your-api-password
KLARNA_REGION=EU
KLARNA_MODE=test$klarna = new PhpKlarna(
$_ENV['KLARNA_USERNAME'],
$_ENV['KLARNA_PASSWORD'],
$_ENV['KLARNA_REGION'],
$_ENV['KLARNA_MODE']
);// 1. Create a payment session
$sessionData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 10000, // $100.00 in cents
'order_lines' => [
[
'name' => 'Test Product',
'quantity' => 1,
'unit_price' => 10000,
'total_amount' => 10000
]
]
];
$session = $klarna->createSession($sessionData);
echo "Session ID: " . $session->session_id;
// 2. After customer completes payment, create order
$orderData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 10000,
'order_lines' => $sessionData['order_lines']
];
$order = $klarna->createOrderFromAuthorizationToken(
'auth-token-from-frontend',
$orderData
);
echo "Order ID: " . $order->order_id;The Payments API handles the core payment flow including sessions, authorizations, and order creation.
Creates a new payment session for Klarna Payments.
$sessionData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 50000, // $500.00 in cents
'order_tax_amount' => 4167, // Tax amount in cents
'order_lines' => [
[
'type' => 'physical',
'name' => 'Premium Headphones',
'quantity' => 2,
'unit_price' => 25000,
'tax_rate' => 1000, // 10% = 1000
'total_amount' => 50000,
'total_discount_amount' => 0,
'total_tax_amount' => 4167
]
],
'merchant_urls' => [
'terms' => 'https://example.com/terms',
'checkout' => 'https://example.com/checkout',
'confirmation' => 'https://example.com/confirmation',
'push' => 'https://example.com/push'
]
];
try {
$session = $klarna->createSession($sessionData);
echo "Session created successfully!\n";
echo "Session ID: " . $session->session_id . "\n";
echo "Client Token: " . $session->client_token . "\n";
} catch (Exception $e) {
echo "Error creating session: " . $e->getMessage();
}After customer completes payment, convert the authorization to an order.
$authToken = 'klarna-auth-token-from-frontend';
$orderData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 50000,
'order_tax_amount' => 4167,
'order_lines' => [
[
'type' => 'physical',
'name' => 'Premium Headphones',
'quantity' => 2,
'unit_price' => 25000,
'tax_rate' => 1000,
'total_amount' => 50000,
'total_tax_amount' => 4167
]
],
'merchant_reference1' => 'ORDER-12345',
'merchant_reference2' => 'STORE-ABC'
];
try {
$order = $klarna->createOrderFromAuthorizationToken($authToken, $orderData);
echo "Order created successfully!\n";
echo "Order ID: " . $order->order_id . "\n";
echo "Klarna Reference: " . $order->klarna_reference . "\n";
} catch (Exception $e) {
echo "Error creating order: " . $e->getMessage();
}Create a reusable customer token for future purchases.
$authToken = 'klarna-auth-token-from-frontend';
$tokenData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'billing_address' => [
'given_name' => 'John',
'family_name' => 'Doe',
'email' => '[email protected]',
'street_address' => '123 Main St',
'postal_code' => '12345',
'city' => 'Anytown',
'region' => 'CA',
'country' => 'US'
]
];
try {
$customerToken = $klarna->createCustomerToken($authToken, $tokenData);
echo "Customer token created: " . $customerToken->token_id . "\n";
} catch (Exception $e) {
echo "Error creating customer token: " . $e->getMessage();
}Cancel an unused authorization token.
$authToken = 'klarna-auth-token-to-cancel';
try {
$result = $klarna->cancelAuthorization($authToken, []);
echo "Authorization cancelled successfully\n";
} catch (Exception $e) {
echo "Error cancelling authorization: " . $e->getMessage();
}The Orders API handles post-purchase order management including captures, refunds, and order updates.
Retrieve complete order information.
$orderId = 'klarna-order-id';
try {
$order = $klarna->order($orderId);
echo "Order Status: " . $order->status . "\n";
echo "Order Amount: " . $order->order_amount . "\n";
echo "Captured Amount: " . $order->captured_amount . "\n";
echo "Refunded Amount: " . $order->refunded_amount . "\n";
} catch (Exception $e) {
echo "Error retrieving order: " . $e->getMessage();
}Capture all or part of an authorized order.
$orderId = 'klarna-order-id';
$captureData = [
'captured_amount' => 25000, // $250.00 in cents
'description' => 'Partial capture for shipped items',
'order_lines' => [
[
'type' => 'physical',
'name' => 'Premium Headphones',
'quantity' => 1,
'unit_price' => 25000,
'total_amount' => 25000
]
]
];
try {
$capture = $klarna->createCapture($orderId, $captureData);
echo "Capture successful!\n";
echo "Capture ID: " . $capture->capture_id . "\n";
} catch (Exception $e) {
echo "Error capturing payment: " . $e->getMessage();
}Process a full or partial refund.
$orderId = 'klarna-order-id';
$refundData = [
'refunded_amount' => 10000, // $100.00 refund
'description' => 'Product return refund',
'order_lines' => [
[
'type' => 'physical',
'name' => 'Returned Item',
'quantity' => 1,
'unit_price' => 10000,
'total_amount' => 10000
]
]
];
try {
$refund = $klarna->createRefund($orderId, $refundData);
echo "Refund processed successfully!\n";
} catch (Exception $e) {
echo "Error processing refund: " . $e->getMessage();
}$orderId = 'klarna-order-id';
// Acknowledge order (confirm you received it)
try {
$klarna->acknowledgeOrder($orderId);
echo "Order acknowledged\n";
} catch (Exception $e) {
echo "Error acknowledging order: " . $e->getMessage();
}
// Cancel order (if not captured)
try {
$klarna->cancelOrder($orderId);
echo "Order cancelled\n";
} catch (Exception $e) {
echo "Error cancelling order: " . $e->getMessage();
}
// Extend authorization time (add 7 days)
try {
$klarna->extendAuthorizationTime($orderId);
echo "Authorization time extended\n";
} catch (Exception $e) {
echo "Error extending authorization: " . $e->getMessage();
}
// Release remaining authorization
try {
$klarna->releaseRemainingAuthorization($orderId);
echo "Remaining authorization released\n";
} catch (Exception $e) {
echo "Error releasing authorization: " . $e->getMessage();
}$orderId = 'klarna-order-id';
// Update merchant references
$merchantData = [
'merchant_reference1' => 'NEW-ORDER-REF-123',
'merchant_reference2' => 'UPDATED-STORE-REF'
];
try {
$klarna->updateMerchantReferences($orderId, $merchantData);
echo "Merchant references updated\n";
} catch (Exception $e) {
echo "Error updating merchant references: " . $e->getMessage();
}
// Update customer details
$customerData = [
'billing_address' => [
'given_name' => 'John',
'family_name' => 'Doe',
'email' => '[email protected]',
'street_address' => '456 New Address St',
'postal_code' => '54321',
'city' => 'New City',
'region' => 'NY',
'country' => 'US'
],
'shipping_address' => [
'given_name' => 'John',
'family_name' => 'Doe',
'street_address' => '456 New Address St',
'postal_code' => '54321',
'city' => 'New City',
'region' => 'NY',
'country' => 'US'
]
];
try {
$klarna->updateCustomerUpdate($orderId, $customerData);
echo "Customer details updated\n";
} catch (Exception $e) {
echo "Error updating customer details: " . $e->getMessage();
}The Checkout API provides a complete checkout solution with Klarna's hosted checkout.
Create a new checkout session with a complete shopping experience.
$checkoutData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 75000, // $750.00
'order_tax_amount' => 6250,
'order_lines' => [
[
'type' => 'physical',
'name' => 'Wireless Mouse',
'quantity' => 3,
'unit_price' => 25000,
'tax_rate' => 1000,
'total_amount' => 75000,
'total_tax_amount' => 6250
]
],
'merchant_urls' => [
'terms' => 'https://example.com/terms',
'checkout' => 'https://example.com/checkout?order_id={checkout.order.id}',
'confirmation' => 'https://example.com/confirmation?order_id={checkout.order.id}',
'push' => 'https://example.com/push?order_id={checkout.order.id}'
],
'options' => [
'allow_separate_shipping_address' => true,
'date_of_birth_mandatory' => false,
'require_validate_callback_success' => true
],
'external_payment_methods' => [
[
'name' => 'PayPal',
'redirect_url' => 'https://example.com/paypal',
'image_url' => 'https://example.com/paypal-logo.png'
]
]
];
try {
$checkout = $klarna->createCheckoutOrder($checkoutData);
echo "Checkout created successfully!\n";
echo "Order ID: " . $checkout->order_id . "\n";
echo "HTML Snippet: " . $checkout->html_snippet . "\n";
} catch (Exception $e) {
echo "Error creating checkout: " . $e->getMessage();
}Get the current state of a checkout order.
$checkoutOrderId = 'checkout-order-id';
try {
$checkout = $klarna->getCheckoutOrder($checkoutOrderId);
echo "Checkout Status: " . $checkout->status . "\n";
echo "Order Amount: " . $checkout->order_amount . "\n";
if ($checkout->status === 'checkout_complete') {
echo "Klarna Reference: " . $checkout->klarna_reference . "\n";
}
} catch (Exception $e) {
echo "Error retrieving checkout: " . $e->getMessage();
}Modify an existing checkout order (only possible before completion).
$checkoutOrderId = 'checkout-order-id';
$updateData = [
'order_amount' => 85000, // Updated amount
'order_tax_amount' => 7083,
'order_lines' => [
[
'type' => 'physical',
'name' => 'Wireless Mouse',
'quantity' => 3,
'unit_price' => 25000,
'tax_rate' => 1000,
'total_amount' => 75000,
'total_tax_amount' => 6250
],
[
'type' => 'shipping_fee',
'name' => 'Express Shipping',
'quantity' => 1,
'unit_price' => 10000,
'tax_rate' => 1000,
'total_amount' => 10000,
'total_tax_amount' => 833
]
]
];
try {
$updated = $klarna->updateCheckoutOrder($checkoutOrderId, $updateData);
echo "Checkout updated successfully!\n";
} catch (Exception $e) {
echo "Error updating checkout: " . $e->getMessage();
}Manage stored customer payment methods for recurring purchases.
Retrieve details about a stored customer token.
$tokenId = 'customer-token-id';
try {
$token = $klarna->customerToken($tokenId);
echo "Token Status: " . $token->status . "\n";
echo "Payment Method: " . $token->payment_method_type . "\n";
echo "Masked Number: " . $token->masked_number . "\n";
} catch (Exception $e) {
echo "Error retrieving customer token: " . $e->getMessage();
}Use a stored customer token to create a new order.
$tokenId = 'customer-token-id';
$orderData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 35000,
'order_tax_amount' => 2917,
'order_lines' => [
[
'type' => 'physical',
'name' => 'Monthly Subscription Box',
'quantity' => 1,
'unit_price' => 35000,
'tax_rate' => 1000,
'total_amount' => 35000,
'total_tax_amount' => 2917
]
],
'merchant_reference1' => 'SUBSCRIPTION-789',
'auto_capture' => true
];
try {
$order = $klarna->createOrderFromCustomerToken($tokenId, $orderData);
echo "Recurring order created!\n";
echo "Order ID: " . $order->order_id . "\n";
echo "Fraud Status: " . $order->fraud_status . "\n";
} catch (Exception $e) {
echo "Error creating order from token: " . $e->getMessage();
}Customize the Guzzle HTTP client for specific needs:
use GuzzleHttp\Client;
$klarna = new PhpKlarna('username', 'password', 'EU', 'test');
// Create custom client with additional options
$customClient = new Client([
'base_uri' => $klarna->getBaseUri('EU', 'test'),
'timeout' => 30,
'verify' => true, // Enable SSL verification
'headers' => [
'Authorization' => 'Basic ' . base64_encode('username:password'),
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'User-Agent' => 'MyApp/1.0'
]
]);
$klarna->setClient($customClient);The SDK provides specific exceptions for different error scenarios:
use Vrajroham\PhpKlarna\Exceptions\ValidationException;
use Vrajroham\PhpKlarna\Exceptions\NotFoundException;
use Vrajroham\PhpKlarna\Exceptions\FailedActionException;
try {
$order = $klarna->order('invalid-order-id');
} catch (ValidationException $e) {
// Handle validation errors (HTTP 422)
echo "Validation Error: " . json_encode($e->getErrors());
} catch (NotFoundException $e) {
// Handle not found errors (HTTP 404)
echo "Resource not found";
} catch (FailedActionException $e) {
// Handle other API errors (HTTP 400)
echo "API Error: " . $e->getMessage();
} catch (Exception $e) {
// Handle any other errors
echo "Unexpected Error: " . $e->getMessage();
}The SDK includes utilities for working with Klarna's date formats:
// Convert date to Klarna format
$klarnaDate = $klarna->convertDateFormat('2023-12-25 15:30:00', 'Y-m-d\TH:i:s\Z');
echo $klarnaDate; // 2023-12-25T15:30:00Z
// Default format (YmdHis)
$defaultFormat = $klarna->convertDateFormat('2023-12-25 15:30:00');
echo $defaultFormat; // 20231225153000While not directly part of this SDK, here's how to validate Klarna webhooks:
function validateKlarnaWebhook($payload, $signature, $secret) {
$calculatedSignature = base64_encode(
hash_hmac('sha256', $payload, $secret, true)
);
return hash_equals($signature, $calculatedSignature);
}
// In your webhook endpoint
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_KLARNA_HMAC_SHA256'] ?? '';
if (validateKlarnaWebhook($payload, $signature, 'your-webhook-secret')) {
$data = json_decode($payload, true);
// Process webhook data
} else {
http_response_code(401);
exit('Invalid signature');
}- Environment Management: Always use environment variables for credentials
- Error Handling: Implement comprehensive error handling for all API calls
- Logging: Log API responses for debugging and audit trails
- Idempotency: Use unique merchant references to prevent duplicate orders
- Security: Never store API credentials in version control
- Testing: Always test thoroughly in playground environment before going live
// Example with comprehensive error handling and logging
function createKlarnaOrder($authToken, $orderData, $logger = null) {
try {
$klarna = new PhpKlarna(
$_ENV['KLARNA_USERNAME'],
$_ENV['KLARNA_PASSWORD'],
$_ENV['KLARNA_REGION'],
$_ENV['KLARNA_MODE']
);
$order = $klarna->createOrderFromAuthorizationToken($authToken, $orderData);
if ($logger) {
$logger->info('Klarna order created', [
'order_id' => $order->order_id,
'klarna_reference' => $order->klarna_reference,
'amount' => $orderData['order_amount']
]);
}
return $order;
} catch (ValidationException $e) {
if ($logger) {
$logger->error('Klarna validation error', ['errors' => $e->getErrors()]);
}
throw new Exception('Invalid order data provided');
} catch (Exception $e) {
if ($logger) {
$logger->error('Klarna API error', ['message' => $e->getMessage()]);
}
throw new Exception('Payment processing failed');
}
}Run the test suite:
composer testRun tests with coverage:
composer test-coverage- Use Playground Environment: Always test with Klarna's playground environment first
- Test Error Scenarios: Verify your error handling works correctly
- Validate Webhooks: Test webhook validation and processing
- Test All Flows: Test complete payment flows from session to capture/refund
Example test with PHPUnit:
class KlarnaIntegrationTest extends TestCase
{
private $klarna;
protected function setUp(): void
{
$this->klarna = new PhpKlarna(
'test-username',
'test-password',
'EU',
'test'
);
}
public function testCreateSession()
{
$sessionData = [
'purchase_country' => 'US',
'purchase_currency' => 'USD',
'locale' => 'en-US',
'order_amount' => 10000,
'order_lines' => [
[
'name' => 'Test Product',
'quantity' => 1,
'unit_price' => 10000,
'total_amount' => 10000
]
]
];
$session = $this->klarna->createSession($sessionData);
$this->assertNotNull($session->session_id);
$this->assertNotNull($session->client_token);
}
}Problem: Getting 401 Unauthorized errors Solution:
- Verify your username and password are correct
- Check that you're using the right region (EU/NA/OC)
- Ensure you're using test credentials with playground URLs
Problem: ValidationException about invalid region
Solution: Use uppercase region codes: 'EU', 'NA', or 'OC'
Problem: SSL verification failures in development Solution:
// Only for development - never in production
$customClient = new Client([
'verify' => false // Disable SSL verification
]);
$klarna->setClient($customClient);Problem: NotFoundException when accessing orders
Solution:
- Verify the order ID is correct
- Check that the order was created in the same environment (test/live)
- Ensure sufficient time has passed for order creation to complete
Q: Can I use this package with Laravel?
A: Yes! This package works perfectly with Laravel. Add credentials to your .env file and use dependency injection.
Q: How do I handle webhooks? A: Klarna sends webhooks for order events. Implement webhook validation using HMAC-SHA256 as shown in the advanced usage section.
Q: What's the difference between Payments and Checkout APIs? A: Payments API gives you more control over the UI, while Checkout API provides Klarna's hosted checkout experience.
Q: Can I test without real money? A: Yes! Use the playground environment with test credentials. No real money is processed.
Q: How do I go from test to production? A: Change the mode from 'test' to 'live' and use your production credentials from Klarna.
Q: What currencies are supported? A: Klarna supports many currencies. Check Klarna's documentation for the complete list.
Q: How do I handle different regions? A: Set the appropriate region (EU/NA/OC) when initializing the client based on your merchant account.
- Documentation: Klarna Developers
- Issues: GitHub Issues
- Email: [email protected]
Please see CHANGELOG for more information about recent changes.
Please see CONTRIBUTING for details on how to contribute.
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.
Built with β€οΈ for the PHP community