Integration Architecture and Data Flow
Klarna Payments API Architecture
Klarna Payments operates through a distributed API architecture with regional endpoints. The European cluster uses api.klarna.com while the North American cluster uses api-na.klarna.com. Your Odoo integration must target the correct regional API based on your merchant account configuration. Each API call requires specific HTTP headers including Authorization, Content-Type, and Klarna-specific user agent strings.
The Klarna system employs OAuth 2.0 client credentials flow for server-to-server authentication. Your Odoo instance obtains an access token using your merchant credentials before making any API requests. Tokens expire after one hour, requiring your integration to implement token refresh logic. Failed authentication attempts trigger account lockdown after five consecutive failures within ten minutes.
Data Flow Patterns
Customer payment initiation starts when Odoo generates a Klarna payment session. Your storefront sends cart details including product names, quantities, and prices to Odoo. The system transforms this data into Klarna’s order structure and creates a client token. This token enables your frontend to render Klarna’s payment widget without direct server access.
Payment authorization occurs when customers complete the Klarna checkout flow. Klarna sends an authorization event to your configured webhook endpoint. Odoo processes this webhook and captures the payment authorization details. The system creates a sales order with the Klarna payment reference attached. Order confirmation emails trigger only after successful payment capture.
Order management flows handle post-purchase operations like captures, refunds, and cancellations. Odoo initiates payment capture when orders reach the shipping stage. The system sends capture requests to Klarna with the exact amount to collect. Refund operations follow a similar pattern with amount validation against the original capture total. Cancellations void authorized payments before capture completion.
Webhook Processing System
Klarna webhooks provide real-time payment status updates to your Odoo instance. Your integration must expose a secure endpoint at /klarna/webhook that accepts POST requests. The endpoint validates webhook signatures using your secret key before processing any data. Failed validations log security events and reject the payload without further processing.
The webhook handler parses JSON payloads containing payment session updates. Each event type requires specific processing logic - authorization events create orders while capture events update payment status. The system implements idempotency checks using Klarna’s event ID to prevent duplicate processing. Database transactions ensure data consistency across order and payment records.
Step-by-Step Configuration
Odoo Module Structure
Create a new Odoo module named payment_klarna with standard module structure. The manifest.py file declares dependencies on payment, sale, and account modules. Your models directory contains Python files for payment transaction handling and webhook processing. Security subdirectory houses ir.model.access.csv for permission definitions.
The module initialization file imports critical classes including PaymentProvider and PaymentTransaction. You inherit from these base classes to implement Klarna-specific payment processing. The module template includes static descriptions and images for the Odoo app store. Proper module structure ensures smooth installation and upgrade paths.
# __manifest__.py
{
'name': 'Klarna Payments',
'version': '18.0.1.0.0',
'category': 'Accounting/Payment',
'depends': ['payment', 'sale', 'account'],
'data': [
'views/payment_klarna_templates.xml',
'views/payment_provider_views.xml',
'data/payment_provider_data.xml',
],
'application': True,
}
Payment Provider Configuration
Extend the payment.provider model to add Klarna-specific configuration fields. Create fields for API credentials including username, password, and test mode toggle. Add region selection with options for Europe and North America. Configure webhook secret key storage with proper encryption using Odoo’s fields.Encrypted class.
The provider form view groups settings into logical sections - API credentials, operational settings, and webhook configuration. Smart buttons provide quick access to transaction logs and synchronization status. Test mode enables sandbox API endpoints with simulated payment flows. Region selection determines the base API URL for all outgoing requests.
class PaymentProviderKlarna(models.Model):
_inherit = 'payment.provider'
code = fields.Char(default='klarna')
klarna_username = fields.Char(string='API Username')
klarna_password = fields.Encrypted(string='API Password')
klarna_region = fields.Selection([
('eu', 'Europe'),
('na', 'North America')], default='eu')
klarna_webhook_secret = fields.Encrypted(string='Webhook Secret')
API Client Implementation
Build a dedicated Klarna API client class that handles authentication and request signing. The client manages access token lifecycle with automatic refresh before expiration. Each API method implements retry logic for transient network failures. The client logs all requests and responses for debugging purposes without storing sensitive data.
The client class constructor accepts provider configuration and initializes the appropriate base URL. API methods cover the complete payment lifecycle - create session, place order, capture payment, and issue refunds. Error handling translates HTTP status codes into meaningful business exceptions. Timeout settings prevent thread blocking during API unavailability.
class KlarnaAPIClient:
def __init__(self, provider):
self.provider = provider
self.base_url = self._get_base_url()
self.access_token = None
def _get_base_url(self):
if self.provider.klarna_region == 'na':
return 'https://api-na.klarna.com'
return 'https://api.klarna.com'
def _ensure_token(self):
if not self.access_token or self.token_expired():
self._refresh_token()
def create_session(self, order_data):
self._ensure_token()
headers = {
'Authorization': f'Bearer {self.access_token}',
'Content-Type': 'application/json'
}
response = requests.post(
f'{self.base_url}/payments/v1/sessions',
json=order_data,
headers=headers,
timeout=10
)
response.raise_for_status()
return response.json()
Frontend Integration
Configure Odoo’s payment form to load the Klarna JavaScript SDK when the provider is selected. The initialization script injects the Klarna payment widget into your checkout page. Client token generation happens asynchronously during page load to minimize perceived latency.
The payment form handles widget initialization with proper error boundaries. JavaScript events manage the payment authorization flow and submit results to Odoo. The implementation supports both modal and inline widget rendering based on your layout requirements. Mobile responsiveness ensures consistent experience across all device types.
odoo.define('payment_klarna.payment_form', require => {
'use strict';
const paymentForm = require('payment.payment_form');
paymentForm.include({
init: function() {
this._super.apply(this, arguments);
this.klarnaWidget = null;
},
_processKlarnaPayment: function() {
this._loadKlarnaSDK().then(() => {
this._initializeKlarnaWidget();
});
}
});
});
Webhook Endpoint Setup
Create a dedicated controller for Klarna webhook processing at /klarna/webhook. The controller implements CSRF protection exemption for external webhook calls. Request validation checks the Klarna-Signature header against your stored secret. Payload parsing extracts the event type and associated data for further processing.
The webhook handler delegates to specific methods based on event type - payment_capture, payment_cancellation, or payment_failed. Each handler method creates background jobs for reliable processing under high load. Database transactions ensure atomic operation for each webhook event. Success responses return HTTP 200 within two seconds to acknowledge receipt.
@http.route('/klarna/webhook', type='json', auth='public', csrf=False)
def klarna_webhook(self):
request_data = request.get_json_data()
signature = request.httprequest.headers.get('Klarna-Signature')
if not self._verify_signature(signature, request_data):
raise ValueError('Invalid webhook signature')
event_type = request_data['event_type']
event_data = request_data['data']
if event_type == 'payment_capture_completed':
self._handle_capture_event(event_data)
return jsonify({'status': 'processed'})
Data Mapping and Transformation
Order Data Structure Mapping
Klarna’s order line specification requires precise mapping from Odoo’s sale order structure. Each order line transforms into Klarna’s item format with name, quantity, unit_price, and tax_rate fields. The total_amount field must match the sum of all line items including taxes and shipping. Odoo’s product variants require special handling to preserve attribute information in the reference field.
Product type mapping converts Odoo’s product categories to Klarna’s product types - physical, digital, gift_card, or discount. Shipping fee lines map to the shipping_fee type with zero tax rate for tax-inclusive pricing. Discount lines require negative unit prices and the discount type designation. The cart total validation ensures Klarna’s calculated amount matches Odoo’s order total.
def _map_order_lines(self, order):
lines = []
for line in order.order_line:
if line.product_id.type == 'service':
product_type = 'digital'
else:
product_type = 'physical'
lines.append({
'type': product_type,
'name': line.name,
'quantity': line.product_uom_qty,
'unit_price': int(line.price_unit * 100),
'tax_rate': int(line.tax_id.amount * 10000),
'total_amount': int(line.price_total * 100),
})
# Add shipping line
if order.carrier_id:
lines.append({
'type': 'shipping_fee',
'name': order.carrier_id.name,
'quantity': 1,
'unit_price': int(order.delivery_price * 100),
'tax_rate': 0,
'total_amount': int(order.delivery_price * 100),
})
return lines
Customer Address Transformation
Klarna’s address format requires structured data that differs from Odoo’s partner fields. The mapping process extracts street name and number from Odoo’s single street field using pattern matching. Customer title conversion maps Odoo’s selection fields to Klarna’s accepted values - mr, mrs, or miss. Phone number formatting ensures E.164 compliance with country code prefix.
Address validation occurs before session creation to prevent payment authorization failures. The system checks for required fields including postal code, city, and country code. Business customer detection triggers different address fields for company names and organization numbers. Regional address formats accommodate country-specific requirements like Swedish apartment numbers.
def _map_address(self, partner):
street_name, street_number = self._split_street(partner.street)
address = {
'given_name': partner.first_name,
'family_name': partner.last_name,
'email': partner.email,
'street_address': street_name,
'street_number': street_number,
'postal_code': partner.zip,
'city': partner.city,
'country': partner.country_id.code,
}
if partner.company_type == 'company':
address['organization_name'] = partner.commercial_company_name
address['organization_registration_id'] = partner.vat
return address
Payment Status Synchronization
Odoo’s payment transaction states map to Klarna’s payment status with specific transition logic. The authorized state in Klarna corresponds to Odoo’s authorized state while captured moves to done. Cancelled payments in Klarna update Odoo transactions to cancelled with proper reason codes. Failed payments log error messages and maintain the error state for manual intervention.
Status synchronization handles edge cases like partial captures and refunds. Partial capture operations create new payment transactions linked to the original authorization. Refund transactions maintain reference to the original capture for audit purposes. The system prevents state transitions that violate business rules, like capturing already cancelled payments.
Tax Calculation Alignment
Klarna requires tax amounts per order line rather than Odoo’s aggregated tax structure. The integration calculates line-level taxes using Odoo’s tax computation engine before sending to Klarna. Tax rate precision ensures Klarna’s calculation matches Odoo’s to prevent payment authorization mismatches.
Tax-exempt customers trigger special handling with zero tax rates across all order lines. The system validates tax configuration before payment session creation to identify calculation discrepancies. Cross-border tax rules require country-specific tax engine configuration for accurate EU VAT handling.
Error Handling and Resilience
Common API Error Patterns
Klarna’s API returns structured error responses with HTTP status codes and error identifiers. Authentication failures return 401 status with invalid_credentials error code. Rate limit violations trigger 429 responses with detailed retry-after headers. Validation errors provide field-specific messages in the error payload for debugging.
The integration categorizes errors into retryable and non-retryable types. Network timeouts and server errors (5xx) qualify for automatic retry with exponential backoff. Business logic errors like invalid order data require code fixes before retry attempts. The system logs error contexts without exposing sensitive credentials in log files.
def _handle_api_error(self, error):
if isinstance(error, requests.exceptions.Timeout):
raise RetryableError('Klarna API timeout') from error
elif isinstance(error, requests.exceptions.ConnectionError):
raise RetryableError('Klarna connection error') from error
if hasattr(error, 'response') and error.response:
status_code = error.response.status_code
if status_code >= 500:
raise RetryableError('Klarna server error') from error
elif status_code == 429:
raise RetryableError('Rate limit exceeded') from error
raise BusinessError(str(error))
Webhook Failure Recovery
Webhook processing failures require robust retry mechanisms with dead letter queue handling. The system implements idempotent webhook processing using Klarna’s event ID to prevent duplicate order creation. Failed webhook events enter a retry queue with increasing delays between attempts. Permanent failures after five retries move to a manual review queue.
Webhook signature verification failures trigger immediate security alerts to system administrators. The system blocks IP addresses with repeated authentication failures using Odoo’s IP filtering system. Payload validation rejects malformed JSON with detailed error logging for debugging.
Order Synchronization Conflicts
Race conditions occur when manual order updates in Odoo conflict with Klarna webhook processing. The integration uses Odoo’s pessimistic locking to prevent simultaneous order status updates. Conflict resolution rules prioritize Klarna’s payment status over manual user changes. The audit trail logs all synchronization conflicts for reconciliation purposes.
Partial synchronization failures trigger compensation transactions to maintain system consistency. Failed capture operations reverse the order confirmation process and notify customers of payment issues. The system provides manual override capabilities for exceptional cases requiring human intervention.
Database Transaction Management
Critical operations wrap database changes in atomic transactions to prevent data corruption. Payment capture processes use two-phase commit patterns between Odoo and Klarna API calls. Transaction rollback handles API failures after local database updates. The system maintains audit logs of all transaction boundaries for debugging complex failures.
Testing and Validation
Test Environment Configuration
Establish a dedicated test environment using Klarna’s sandbox API endpoints. Create test merchant accounts for each region to validate regional API differences. Configure test webhook endpoints that simulate production URL structure. Generate test products with varied tax configurations to validate calculation accuracy.
The test suite includes dummy customer profiles with different address formats and business types. Test payment methods cover all Klarna payment options available in your target markets. Load testing simulates peak traffic patterns to identify performance bottlenecks before production deployment.
Payment Flow Test Scenarios
Test the complete payment lifecycle from session creation through refund processing. Validate successful payment authorization creates orders with correct payment references. Test partial capture scenarios for orders with split shipment requirements. Verify cancellation flows properly void authorized payments before capture.
Error condition testing covers payment declines, insufficient funds, and expired authorization sessions. Test timeout handling by simulating slow API responses from Klarna servers. Validate duplicate webhook processing doesn’t create duplicate orders in Odoo.
Data Validation Procedures
Implement schema validation for all Klarna API requests and responses. Use JSON Schema definitions to validate webhook payload structure before processing. Create data quality checks that verify tax calculation consistency between systems. Validate address formatting meets Klarna’s requirements for each target country.
Order total validation ensures the sum of line items matches the order total within acceptable rounding tolerance. Product reference mapping verification confirms product variants maintain their identity through the payment flow. Customer data validation checks personal identification number formatting for regional requirements.
Performance Benchmarking
Measure API response times under different load conditions to establish performance baselines. Test webhook processing capacity by simulating high-volume payment events. Validate database query performance during order synchronization operations. Establish performance thresholds that trigger scaling operations.
Load testing identifies the maximum concurrent payment sessions your infrastructure supports. Stress testing determines breaking points for graceful degradation planning. Endurance testing verifies system stability under sustained load over multiple hours.
Security Considerations
API Credential Management
Store Klarna API credentials using Odoo’s encrypted fields with key rotation every ninety days. Implement credential versioning to support seamless key updates without service interruption. Restrict access to credential configuration to authorized administrators only. Audit credential usage patterns to detect anomalous access.
The system masks credential exposure in log files and user interface elements. API client implementations never cache credentials in memory beyond individual request cycles. Credential backup procedures maintain security while ensuring business continuity.
Webhook Security Implementation
Validate every webhook request using the Klarna-Signature header with HMAC verification. Implement timestamp validation to reject requests older than five minutes to prevent replay attacks. Rate limit webhook endpoints by source IP to prevent denial of service attacks. Log all webhook authentication attempts for security monitoring.
Webhook payload processing occurs after successful signature verification only. The system rejects payloads with invalid JSON structure before any business logic execution. IP whitelisting capabilities restrict webhook sources to Klarna’s published IP ranges.
Data Protection Compliance
The integration follows GDPR principles for customer data minimization and retention. Personal data flows through secure channels with encryption in transit and at rest. Audit trails track data access for compliance reporting requirements. Data retention policies automatically purge sensitive information after legal requirements expire.
Payment card data never touches Odoo’s database, remaining in Klarna’s PCI-compliant environment. Customer personal information transfers only during essential payment operations. The system provides data export and deletion capabilities for individual customer requests.
Performance Optimization
API Call Optimization
Reduce Klarna API calls through strategic caching of static data like product information. Batch multiple order line updates into single API calls where possible. Implement request deduplication to prevent identical API calls within short time windows. Use conditional requests with ETag headers to minimize data transfer.
The payment session creation process precomputes required data to minimize database queries during API calls. Order synchronization operations use bulk processing to handle multiple orders in single transactions. API response caching applies to product tax rates and customer address validation results.
Database Performance Tuning
Optimize database indexes on payment reference fields to accelerate order lookups. Partition transaction tables by date to maintain query performance as data volume grows. Implement read replicas for reporting queries that don’t require real-time data. Regular database maintenance prevents index fragmentation and statistics staleness.
The system uses database connection pooling to reduce connection overhead for frequent API operations. Query optimization focuses on payment transaction reconciliation processes that scan large datasets. Background job processing moves heavy operations outside the request-response cycle.
Background Processing Strategy
Implement asynchronous processing for non-critical path operations like analytics and reporting. Use Odoo’s queue job system to handle webhook processing outside real-time constraints. Schedule heavy operations like daily reconciliation during off-peak hours. Implement priority queues to ensure payment processing takes precedence over maintenance tasks.
Background job monitoring provides alerting for stuck jobs and queue backlog growth. Automatic retry with exponential backoff handles transient failures without manual intervention. Job idempotency ensures safe retry of potentially duplicate operations.