Index: /mods/mod_klarna/KlarnaOrder.php
===================================================================
--- /mods/mod_klarna/KlarnaOrder.php	(revision 8426)
+++ /mods/mod_klarna/KlarnaOrder.php	(revision 8426)
@@ -0,0 +1,31 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 05.03.24
+	 * @time: 09:02
+	 */
+	
+	namespace wpsgKlarna\mod_klarna;
+	
+	abstract class KlarnaOrder {
+		
+		public static function buildOrderHash(int $order_id): string {
+		
+			$oOrder = \wpsg_order::getInstance($order_id);
+			
+			$arHash = [$oOrder->getToPay()];
+			
+			foreach ($oOrder->getOrderProducts() as $oOrderProduct) {
+				
+				$arHash[] = $oOrderProduct->getAmount().':'.$oOrderProduct->getPriceSum(WPSG_BRUTTO);
+				
+			}
+			
+			return base64_encode(implode('|', $arHash));
+		
+		}
+		
+	}
Index: /mods/mod_klarna/KlarnaPayment.php
===================================================================
--- /mods/mod_klarna/KlarnaPayment.php	(revision 8426)
+++ /mods/mod_klarna/KlarnaPayment.php	(revision 8426)
@@ -0,0 +1,452 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 04.03.24
+	 * @time: 12:49
+	 */
+	
+	namespace wpsgKlarna\mod_klarna;
+ 
+	class KlarnaPayment {
+		
+		public static function getOrder(int $order_id, string $klarna_order_id): array {
+			
+			list($response_data, $response_header_code, $response_header) = self::callAPI('ordermanagement/v1/orders/'.$klarna_order_id, null, $order_id);
+			
+			$response_json = json_decode($response_data, true);
+			
+			return $response_json;
+			
+		}
+		
+		/**
+		 * @throws \Exception
+		 */
+		public static function captureOrder(int $order_id, string $klarna_order_id): array {
+		
+			$oOrder = \wpsg_order::getInstance($order_id);
+			$capture_amount = $oOrder->getToPay(WPSG_BRUTTO);
+			
+			$request_data = self::getOrderData($order_id) + [
+				'captured_amount' => intval(round($capture_amount, 2) * 100)
+			];
+			
+			list($response_data, $response_header_code, $response_header) = self::callAPI('ordermanagement/v1/orders/'.$klarna_order_id.'/captures', $request_data, $order_id);
+			
+			$response_data = json_decode($response_data, true);
+			
+			if (isset($response_data['error_code'])) {
+			 
+				wpsg_debug($request_data);
+				wpsg_debug($response_data);
+				
+				$oOrder = \wpsg_order::getInstance($order_id);
+				$oOrder->addLogEntry('Klarna Fehler', print_r($response_data, true));
+				
+				throw new \Exception($response_data['error_messages'][0]);
+				
+			} else {
+				
+				if ($response_header_code === 201) {
+					
+					if (!isset($response_header['capture-id']) || !isset($response_header['location'])) throw new \Exception(__('Fehler beim Capture', 'wpsg'));
+					
+					return [
+						'capture-id' => $response_header['capture-id'],
+						'location' => $response_header['location']
+					];
+					
+				}
+				
+			}
+			
+			throw new \Exception(__('Capture nicht mÃ¶glich', 'wpsg'));
+			
+		}
+		
+		public static function createOrderWithAuthorizationToken(int $order_id, string $authorization_token) {
+			
+			$request_data = self::getOrderData($order_id);
+		 
+			list($response_data) = self::callAPI('payments/v1/authorizations/'.$authorization_token.'/order', $request_data, $order_id);
+		
+			$response_data = json_decode($response_data, true);
+			
+			return [
+				'authorized_payment_method' => $response_data['authorized_payment_method'],
+				'fraud_status' => $response_data['fraud_status'],
+				'order_id' => $response_data['order_id']
+			];
+			
+		}
+		
+		/**
+		 * @throws \Exception
+		 */
+		public static function updateSession(string $session_id, int $order_id): void {
+		
+			$request_data = self::getOrderData($order_id);
+			
+			list($response_data, $http_code, $header, $request_data) = self::callAPI('payments/v1/sessions/'.$session_id, $request_data, $order_id);
+		
+			$response_json = json_decode($response_data, true);
+			
+			if (isset($response_data['error_code'])) {
+				
+				wpsg_debug('KlarnaFail: ordermanagement/v1/orders/{}/cancel');
+				wpsg_debug($request_data);
+				wpsg_debug($response_data);
+				
+				throw new \Exception($response_data['error_code']);
+				
+			}
+			
+			if ($http_code !== 204) {
+				
+				wpsg_debug($response_data);
+				
+				throw new \Exception(__('Session konnte nicht aktualisiert werden.', 'wpsg'));
+				
+			}
+			
+		}
+		
+		/**
+		 * Erstellt oder Aktualisiert eine Session anhand der BestellID
+		 * @throws \Exception
+		 */
+		public static function getSession(int $order_id): array {
+			
+			$oOrder = \wpsg_order::getInstance($order_id);
+			
+			$client_token = $oOrder->getMeta('wpsg_mod_klarna_client_token', false, '');
+			$session_id = $oOrder->getMeta('wpsg_mod_klarna_session_id', false, '');
+			
+			if ($client_token === '' || $session_id === '') {
+				
+				$r = self::createSession($order_id);
+			 
+				$oOrder->setMeta('wpsg_mod_klarna_client_token', $r['client_token']);
+				$oOrder->setMeta('wpsg_mod_klarna_session_id', $r['session_id']);
+				
+				return $r;
+				
+			} else {
+	 
+				$session_data = self::getSessionDetails($session_id, $order_id);
+				
+				if ($session_data['status'] === 'incomplete') {
+					
+					self::updateSession($session_id, $order_id);
+					
+				}
+				return [
+					'client_token' => $client_token,
+					'session_id' => $session_id
+				];
+			
+			}
+			
+		}
+		
+		private static function getSessionDetails(string $session_id, int $order_id): array {
+			
+			list($response_data, $response_header, $header, $request_data) = self::callAPI('payments/v1/sessions/'.$session_id, null, $order_id);
+			
+			return json_decode($response_data, true);
+			
+		}
+		
+		/**
+		 * Erstellt eine neue Session
+		 * @param int $order_id
+		 * @return array
+		 * @throws \Exception
+		 */
+		private static function createSession(int $order_id): array {
+			
+			$request_data = self::getOrderData($order_id) + [
+				'intent' => 'buy'
+			];
+			
+			list($response_data, $response_header, $header, $request_data) = self::callAPI('payments/v1/sessions', $request_data, $order_id);
+ 
+			$response_data = json_decode($response_data, true);
+			
+			if (isset($response_data['error_code'])) {
+			 
+				wpsg_debug('KlarnaFail: payments/v1/sessions');
+				wpsg_debug($request_data);
+				wpsg_debug($response_data);
+				
+				$oOrder = \wpsg_order::getInstance($order_id);
+				$oOrder->addLogEntry('Klarna Fehler', print_r($response_data, true));
+				
+				throw new \Exception($response_data['error_code']);
+				
+			}
+			
+			return [
+				'client_token' => $response_data['client_token'],
+				'session_id' => $response_data['session_id']
+			];
+			
+		}
+		
+		private static function getOrderData(int $order_id): array {
+			
+			$oOrder = \wpsg_order::getInstance($order_id);
+			$wpsg_calculation = \wpsg\wpsg_calculation::getOrderCalculation($order_id);
+			$arCalculation = $wpsg_calculation->getCalculationArray();
+			
+			$order_lines = [];
+			
+			foreach ($oOrder->getOrderProducts() as $oOrderProduct) {
+				
+				$row = [
+					'name' => $oOrderProduct->getProductName(),
+					'quantity' => $oOrderProduct->getAmount(),
+					'total_amount' => $oOrderProduct->getPriceSum(WPSG_BRUTTO) * 100,
+					'unit_price' => $oOrderProduct->getPrice(WPSG_BRUTTO) * 100,
+					'total_tax_amount' => intval(round(($oOrderProduct->getPriceSum(WPSG_BRUTTO) - $oOrderProduct->getPriceSum(WPSG_NETTO)), 2) * 100),
+					'tax_rate' => $oOrder->getTaxCountry()->getTax($oOrderProduct->getTaxKey()) * 100,
+					'type' => 'physical'
+				];
+
+				$order_lines[] = $row;
+				
+			}
+
+			// Versandkosten
+			if (sizeof($arCalculation['shipping']) > 0) {
+				
+				foreach ($arCalculation['shipping'] as $shipping_data) {
+				
+					$order_lines[] = [
+						'name' => __('Versandkosten', 'wpsg'),
+						'quantity' => 1,
+						'total_amount' => intval($shipping_data['brutto'] * 100),
+						'unit_price' => intval($shipping_data['brutto'] * 100),
+						'total_tax_amount' => intval(round($shipping_data['tax'], 2) * 100),
+						'tax_rate' => $oOrder->getTaxCountry()->getTax('c') * 100,
+						'type' => 'shipping_fee'
+					];
+					
+				}
+				
+			}
+			
+			// Zahlungskosten
+			if (sizeof($arCalculation['payment']) > 0) {
+				
+				foreach ($arCalculation['payment'] as $payment_data) {
+				
+					$order_lines[] = [
+						'name' => __('Zahlungskosten', 'wpsg'),
+						'quantity' => 1,
+						'total_amount' => intval($payment_data['brutto'] * 100),
+						'unit_price' => intval($payment_data['brutto'] * 100),
+						'total_tax_amount' => intval(round($payment_data['tax'], 2) * 100),
+						'tax_rate' => $oOrder->getTaxCountry()->getTax('c') * 100,
+						'type' => 'surcharge'
+					];
+					
+				}
+				
+			}
+			
+			// Warenkorb Rabatt
+			if (sizeof($arCalculation['discount']) > 0) {
+				
+				foreach ($arCalculation['discount'] as $discount_data) {
+				
+					$order_lines[] = [
+						'name' => __('Warenkorbrabatt', 'wpsg'),
+						'quantity' => 1,
+						'total_amount' => intval($discount_data['brutto'] * 100),
+						'unit_price' => intval($discount_data['brutto'] * 100),
+						'total_tax_amount' => intval(round($discount_data['tax'], 2) * 100),
+						'tax_rate' => $oOrder->getTaxCountry()->getTax('c') * 100,
+						'type' => 'discount'
+					];
+					
+				}
+				
+			}
+			
+			// Gutscheine
+			if (sizeof($arCalculation['voucher']) > 0) {
+				
+				foreach ($arCalculation['voucher'] as $voucher_data) {
+				
+					$order_lines[] = [
+						'name' => __('Gutschein', 'wpsg'),
+						'quantity' => 1,
+						'total_amount' => intval($voucher_data['brutto'] * 100),
+						'unit_price' => intval($voucher_data['brutto'] * 100),
+						'total_tax_amount' => intval(round($voucher_data['tax'], 2) * 100),
+						'tax_rate' => $oOrder->getTaxCountry()->getTax('c') * 100,
+						'type' => 'gift_card'
+					];
+					
+				}
+				
+			}
+			
+			$r = [
+				'acquiring_channel' => 'ECOMMERCE',
+				'order_amount' => $oOrder->getToPay(WPSG_BRUTTO) * 100,
+				'order_lines' => $order_lines,
+				'purchase_country' => $oOrder->getInvoiceCountry()->getShorttext(),
+				'purchase_currency' => \wpsg_ShopController::getShop()->get_option('wpsg_currency'),
+				'merchant_data' => 'BestellID: '.$oOrder->getId().' KundenID: '.$oOrder->getCustomer()->getId(),
+				'merchant_reference1' => $oOrder->getNr(),
+				'merchant_reference2' => $oOrder->getId(),
+				'order_tax_amount' => intval(round($oOrder->getTaxAmount(), 2) * 100),
+				'locale' => 'de-DE',
+				'merchant_urls' => [
+					'terms' => 'https://maennchen1.de', // URL for the terms and conditions page of the merchant. The URL will be displayed inside the Klarna Checkout iFrame.(max 2000 characters)
+					'checkout' => 'https://maennchen1.de', // URL for the checkout page of the merchant. (max 2000 characters)
+					'confirmation' => 'https://maennchen1.de', // URL of the merchant confirmation page. The consumer will be redirected back to the confirmation page if the authorization is successful after the customer clicks on the âPlace Orderâ button inside checkout. The special characters of the confirmation URL should be encoded, e.g. the "space" character should be written as "%20". Then, on top of that, the whole confirmation URL should be encoded. E.g. the "space" character should become "%2520". (max 2000 characters)
+					'push' => 'https://maennchen1.de', // URL that will be used for push notification when an order is completed. Should be different than checkout and confirmation URLs.
+				]
+			];
+	 
+			$r['billing_address'] = [
+				'city' => $oOrder->getInvoiceCity(),
+				'country' => $oOrder->getInvoiceCountry()->getShorttext(),
+				'email' => $oOrder->getCustomer()->getEMail(),
+				'family_name' => $oOrder->getInvoiceName(),
+				'given_name' => $oOrder->getInvoiceFirstName(),
+				//'organization_name' => $oOrder->getInvoiceCompany(),
+				'phone' => $oOrder->getInvoicePhone(),
+				'postal_code' => $oOrder->getInvoiceZip(),
+				'street_address' => $oOrder->getInvoiceStreet()
+			];
+			
+			$r['shipping_address'] = [
+				'city' => $oOrder->getShippingCity(),
+				'country' => $oOrder->getShippingCountry()->getShorttext(),
+				'email' => $oOrder->getCustomer()->getEMail(),
+				'family_name' => $oOrder->getShippingName(),
+				'given_name' => $oOrder->getShippingFirstName(),
+				//'organization_name' => $oOrder->getShippingCompany(),
+				'postal_code' => $oOrder->getShippingZip(),
+				'street_address' => $oOrder->getShippingStreet()
+			];
+			
+			$r['customer'] = [
+				'date_of_birth' => $oOrder->getCustomer()->getBirthdate('Y-m-d')
+			];
+			
+			// wpsg_debug($r);
+			
+			return $r;
+			
+		}
+		
+		private static function callAPI(string $path, ?array $data, ?int $order_id = null): array {
+			
+			if (\wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_sandbox') === '1') {
+				
+				$log_prefix = '(SANDBOX)';
+				$username = \wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_sandbox_user');
+				$password = \wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_sandbox_password');
+				$url = 'https://api.playground.klarna.com/';
+				
+			} else {
+				
+				$log_prefix = '(LIVE)';
+				$username = \wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_api_user');
+				$password = \wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_api_password');
+				$url = 'https://api.klarna.com/';
+				
+			}
+			
+			$ch = curl_init($url.$path);
+			
+			if ($data !== null) {
+				
+				curl_setopt($ch, CURLOPT_POST, true);
+				curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+				
+			}
+			
+			curl_setopt($ch, CURLOPT_HEADER, true);
+			curl_setopt($ch, CURLOPT_HTTPHEADER, [
+				'Content-Type: application/json',
+				'Authorization: Basic '.base64_encode($username.':'.$password)
+			]);
+			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+			
+			$result = curl_exec($ch);
+			
+			if ($result === false) throw new \Exception(__('API Fehler', 'wpsg'));
+			
+			// extract header
+			$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
+			$header = substr($result, 0, $headerSize);
+			$header = self::getHeaders($header);
+			
+			// extract body
+			$result = substr($result, $headerSize);
+			
+			if ($result === false) {
+				
+				wpsg_debug(curl_getinfo($ch));
+				wpsg_debug("?");
+				
+			}
+			
+			$info = curl_getinfo($ch);
+			
+			$httpcode = intval($info['http_code']);
+			
+			if ($order_id !== null && \wpsg_ShopController::getShop()->get_option('wpsg_mod_klarna_debug') === '1') {
+				
+				$json_result = json_decode($result, true);
+				
+				$backtrace = debug_backtrace();
+    			$caller_function = isset($backtrace[1]['function']) ? $backtrace[1]['function'] : 'Unknown';
+    			
+				$oOrder = \wpsg_order::getInstance($order_id);
+				$oOrder->addLogEntry('Klarna API '.$log_prefix.' '.$caller_function, $path.print_r($json_result, true));
+				
+			}
+			
+			curl_close($ch);
+			
+			return [$result, $httpcode, $header, $data];
+			
+		}
+		
+		private static function getHeaders($respHeaders): array {
+			
+			$headers = array();
+			
+			$headerText = substr($respHeaders, 0, strpos($respHeaders, "\r\n\r\n"));
+			
+			foreach (explode("\r\n", $headerText) as $i => $line) {
+				
+				if ($i === 0) {
+					
+					$headers['http_code'] = $line;
+				
+				} else {
+					
+					list ($key, $value) = explode(': ', $line);
+					
+					$headers[$key] = $value;
+				
+				}
+			
+			}
+
+			return $headers;
+
+		}
+		
+	}
Index: /mods/wpsg_mod_klarna.class.php
===================================================================
--- /mods/wpsg_mod_klarna.class.php	(revision 8426)
+++ /mods/wpsg_mod_klarna.class.php	(revision 8426)
@@ -0,0 +1,274 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 04.03.24
+	 * @time: 11:48
+	 */
+	 
+	use wpsgKlarna\mod_klarna\KlarnaPayment;
+	
+	class wpsg_mod_klarna extends \wpsg_mod_basic {
+	 
+		protected static ?wpsg_mod_klarna $instance = null;
+		
+		public function __construct() {
+			
+			parent::__construct();
+			
+			$this->id = 816;
+			$this->name = __('Klarna', 'wpsg');
+			$this->group = __('Zahlungsarten', 'wpsg');
+			$this->desc = __('', 'wpsg');
+ 
+			\spl_autoload_register(function($class_name) {
+
+				$arPath = explode('\\', $class_name);
+		
+				if ($arPath[0] === 'wpsgKlarna') {
+ 
+					if (file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'mod_klarna'.DIRECTORY_SEPARATOR.$arPath[2].'.php')) {
+		
+						require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'mod_klarna'.DIRECTORY_SEPARATOR.$arPath[2].'.php');
+						
+					} else {
+						
+						throw new \Exception(wpsg_translate(__('Klarna Klasse #1# nicht gefunden.', 'wpsg'), $class_name));
+						
+					}
+		
+				}
+		
+			} );
+			
+		}
+		
+		public function addPayment(&$arPayment) {
+			
+			if (!$this->isPaymentisActive()) return;
+			
+			$arPayment[$this->id] = array(
+				'id' => $this->id,
+				'name' => $this->name,
+				'price' => wpsg_tf($this->shop->get_option('wpsg_mod_klarna_fee')),
+				'tax_key' => $this->shop->get_option('wpsg_mod_klarna_tax_key'),
+				'mwst_null' => $this->shop->get_option('wpsg_mod_klarna_notaxcountry'),
+				'hint' => __($this->shop->get_option('wpsg_mod_klarna_hint')).'<div id="wpsg_mod_klarna_widget"></div>',
+				'logo' => $this->shop->getRessourceURL('/mods/mod_klarna/gfx/klarna.svg')
+			);
+			
+		}
+		
+		public function checkout2_inner_prebutton(&$checkout_view) {
+			
+			if (intval($checkout_view['basket']['checkout']['payment']) === $this->id && $this->shop->get_option('wpsg_mod_klarna_checkout') === '1') {
+				
+				$order_id = intval($this->shop->basket->save(false, false, true));
+				
+				list($client_token, $session_id) = array_values(KlarnaPayment::getSession($order_id));
+		 
+				$this->shop->view['wpsg_mod_klarna'] = [
+					'client_token' => $client_token,
+					'oOrder' => \wpsg_order::getInstance($order_id),
+					'url_setAuthToken' => \wpsg_ShopController::getShop()->getURL(\wpsg_ShopController::URL_OVERVIEW, 'wpsg_mod_klarna', 'setAuthToken'),
+					'button_id' => 'wpsg_checkout2button'
+				];
+				$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/pay.phtml');
+				
+				
+			}
+			
+		}
+		
+		public function settings_edit(): void {
+		
+			$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/settings_edit.phtml');
+		
+		}
+		
+		public function order_done(&$order_id, &$done_view) {
+			
+			$oOrder = \wpsg_order::getInstance($order_id);
+			
+			if (intval($oOrder->getPaymentID()) !== $this->id) return;
+		 
+			$authorization_token = $oOrder->getMeta('wpsg_mod_klarna_authorization_token', false, '');
+			$wpsg_mod_klarna_capture_id = $oOrder->getMeta('wpsg_mod_klarna_capture_id', false, '');
+ 
+			if ($authorization_token !== '' && $wpsg_mod_klarna_capture_id === '') {
+	 
+				$r = KlarnaPayment::createOrderWithAuthorizationToken($order_id, $authorization_token);
+				$klarna_order_id = $r['order_id']??'';
+				
+				if ($klarna_order_id !== '') {
+					
+					$oOrder->setMeta('wpsg_mod_klarna_order_id', $r['order_id']);
+					
+					$r = KlarnaPayment::captureOrder($order_id, $r['order_id']);
+					
+					$oOrder->setMeta('wpsg_mod_klarna_capture_id', $r['capture-id']);
+					$oOrder->setMeta('wpsg_mod_klarna_location', $r['location']);
+					
+					$klarna_order_info = KlarnaPayment::getOrder($order_id, $klarna_order_id);
+					
+					if ($klarna_order_info['status'] === 'CAPTURED' && $klarna_order_info['captured_amount'] === intval($oOrder->getToPay(WPSG_BRUTTO) * 100)) {
+						
+						// Bestellung freigeben
+						$this->shop->setOrderStatus($oOrder->id, 100, false);
+						
+						$this->shop->view['wpsg_mod_klarna']['state'] = 'PAYED_DONE';
+						$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/order_done.phtml');
+						return;
+						
+					}
+					
+				}
+				
+			}
+			
+			$klarna_order_id = $oOrder->getMeta('wpsg_mod_klarna_order_id', false, '');
+			
+			if ($klarna_order_id !== '') {
+				
+				$klarna_order_info = KlarnaPayment::getOrder($order_id, $klarna_order_id);
+				
+				if ($klarna_order_info['status'] === 'CAPTURED' && $klarna_order_info['captured_amount'] === intval($oOrder->getToPay(WPSG_BRUTTO) * 100)) {
+					
+					$this->shop->view['wpsg_mod_klarna']['state'] = 'PAYED';
+					$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/order_done.phtml');
+					return;
+					
+				}
+				
+			}
+			
+			list($client_token, $session_id) = array_values(KlarnaPayment::getSession($order_id));
+			
+			$this->shop->view['wpsg_mod_klarna'] = [
+				'state' => 'TOPAY',
+				'client_token' => $client_token,
+				'oOrder' => \wpsg_order::getInstance($order_id),
+				'url_setAuthToken' => \wpsg_ShopController::getShop()->getDoneURL($order_id, 'wpsg_mod_klarna', 'setAuthTokenPay')
+			];
+			$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/order_done.phtml');
+			
+		}
+		
+		public function order_view_afterpayment(&$order_id) {
+			
+			$oOrder = \wpsg_order::getInstance($order_id);
+			
+			if (intval($oOrder->getPaymentID()) == $this->id) {
+				
+				$this->shop->render(dirname(__FILE__).'/../views/mods/mod_klarna/order_view_afterpayment.phtml');
+				
+			}
+			
+		}
+		
+		/**
+		 * Hier kommt man nach Checkout2 hin
+		 * @return void
+		 * @throws \wpsg\Exception
+		 */
+		public function setAuthTokenRedirect() {
+			
+			// Bestellung hole ich mir aus der Session
+			$order_id = intval($_SESSION['wpsg']['order_id']??0);
+			
+			$request = file_get_contents('php://input');
+			$request = json_decode($request, true);
+			
+			if ($order_id > 0 && isset($request['authorization_token'])) {
+			
+				// Authorisierung an Bestellung speichern
+				$oOrder = \wpsg_order::getInstance($order_id);
+				$oOrder->setMeta('wpsg_mod_klarna_authorization_token', $request['authorization_token']);
+				
+				$data = [
+					'success' => true,
+					'href' => \wpsg_ShopController::getShop()->getURL(\wpsg_ShopController::URL_OVERVIEW)
+				];
+				header('Content-Type: application/json; charset=utf-8');
+				echo json_encode($data); exit;
+				
+			} else die("0");
+			
+		}
+		
+		/**
+		 * Hier kommt man nach der Bestellung rein
+		 * @return void
+		 * @throws \wpsg\Exception
+		 */
+		public function setAuthTokenPayRedirect() {
+			
+			$request = file_get_contents('php://input');
+			$request = json_decode($request, true);
+			
+			$order_id = intval($_REQUEST['order_id']??0);
+			
+			if ($order_id > 0 && isset($request['authorization_token'])) {
+			
+				// Authorisierung an Bestellung speichern
+				$oOrder = \wpsg_order::getInstance($order_id);
+				$oOrder->setMeta('wpsg_mod_klarna_authorization_token', $request['authorization_token']);
+	 
+				$data = [
+					'success' => true,
+					'href' => \wpsg_ShopController::getShop()->getDoneURL($order_id)
+				];
+				header('Content-Type: application/json; charset=utf-8');
+				echo json_encode($data); exit;
+				
+			} else die("0");
+			
+		}
+		
+		public function settings_save() {
+			
+			$this->shop->update_option('wpsg_mod_klarna_active', intval($_REQUEST['wpsg_mod_klarna_active']??0));
+			$this->shop->update_option('wpsg_mod_klarna_admin_active', intval($_REQUEST['wpsg_mod_klarna_admin_active']??0));
+			
+			$this->shop->update_option('wpsg_mod_klarna_api_user', sanitize_text_field($_REQUEST['wpsg_mod_klarna_api_user']??''));
+			$this->shop->update_option('wpsg_mod_klarna_api_password', sanitize_text_field($_REQUEST['wpsg_mod_klarna_api_password']??''));
+			
+			$this->shop->update_option('wpsg_mod_klarna_sandbox', intval($_REQUEST['wpsg_mod_klarna_sandbox']??0));
+			$this->shop->update_option('wpsg_mod_klarna_sandbox_user', sanitize_text_field($_REQUEST['wpsg_mod_klarna_sandbox_user']??''));
+			$this->shop->update_option('wpsg_mod_klarna_sandbox_password', sanitize_text_field($_REQUEST['wpsg_mod_klarna_sandbox_password']??''));
+			
+			$this->shop->update_option('wpsg_mod_klarna_fee', sanitize_text_field($_REQUEST['wpsg_mod_klarna_fee']??''));
+			$this->shop->update_option('wpsg_mod_klarna_tax_key', sanitize_text_field($_REQUEST['wpsg_mod_klarna_tax_key']??''));
+			$this->shop->update_option('wpsg_mod_klarna_notaxcountry', intval($_REQUEST['wpsg_mod_klarna_notaxcountry']??0));
+			$this->shop->update_option('wpsg_mod_klarna_hint', sanitize_text_field($_REQUEST['wpsg_mod_klarna_hint']??''));
+			
+			$this->shop->update_option('wpsg_mod_klarna_debug', intval($_REQUEST['wpsg_mod_klarna_debug']??0));
+			$this->shop->update_option('wpsg_mod_klarna_checkout', intval($_REQUEST['wpsg_mod_klarna_checkout']??0));
+			
+		}
+		
+		private function isPaymentisActive(): bool {
+			
+			if (!is_admin()) {
+				
+				if ($this->shop->get_option('wpsg_mod_klarna_active') !== '1') return false;
+				
+				if ($this->shop->get_option('wpsg_mod_payone_admin_active') === '1' && !\current_user_can('administrator')) return false;
+				
+				return true;
+				
+			} else return true;
+			
+		}
+		
+		public static function getInstance(): wpsg_mod_klarna {
+		 
+			if (!isset(static::$instance)) static::$instance = new static;
+			
+			return static::$instance;
+			
+		}
+	
+	}
Index: /views/mods/mod_klarna/gfx/klarna.svg
===================================================================
--- /views/mods/mod_klarna/gfx/klarna.svg	(revision 8426)
+++ /views/mods/mod_klarna/gfx/klarna.svg	(revision 8426)
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="40.4494" viewBox="0 0 100 40.4494"><defs><style>.cls-1{fill:#ffb3c7;}</style></defs><g id="Lager_2" data-name="Lager 2"><g id="Layer_1" data-name="Layer 1"><rect class="cls-1" width="100" height="40.4494" rx="11.7384"/><path d="M80.0772,17.7235a6.194,6.194,0,1,0,0,10.2373v.75h3.5145V16.9727H80.0772Zm-3.1964,8.1388a3.0243,3.0243,0,1,1,3.1849-3.02A3.1059,3.1059,0,0,1,76.8808,25.8623Z"/><rect x="28.2027" y="11.7416" width="3.678" height="16.9694"/><path d="M64.1542,16.6569a4.2694,4.2694,0,0,0-3.62,1.6383V16.9733h-3.5V28.711h3.5421V22.5424a2.4754,2.4754,0,0,1,2.6383-2.6591c1.5447,0,2.4325.9228,2.4325,2.6348V28.711h3.5107V21.2464C69.1577,18.5146,66.9857,16.6569,64.1542,16.6569Z"/><path d="M43,17.7235a6.194,6.194,0,1,0,0,10.2373v.75h3.5145V16.9727H43Zm-3.1965,8.1388a3.0243,3.0243,0,1,1,3.1845-3.02A3.1058,3.1058,0,0,1,39.8034,25.8623Z"/><path d="M51.9513,18.5017V16.9728H48.353V28.7111h3.606v-5.48c0-1.8491,2.0042-2.843,3.3949-2.843.014,0,.0276.0014.0417.0015V16.9735A4.3821,4.3821,0,0,0,51.9513,18.5017Z"/><path d="M87.323,24.5476a2.2059,2.2059,0,1,0,2.206,2.2059A2.2057,2.2057,0,0,0,87.323,24.5476Z"/><path d="M25.6675,11.7384H21.8558a9.7488,9.7488,0,0,1-3.9412,7.8678l-1.51,1.131,5.8513,7.9792h4.8106l-5.3837-7.342A13.5049,13.5049,0,0,0,25.6675,11.7384Z"/><rect x="12.1204" y="11.7384" width="3.8185" height="16.9773"/></g></g></svg>
Index: /views/mods/mod_klarna/order_done.phtml
===================================================================
--- /views/mods/mod_klarna/order_done.phtml	(revision 8426)
+++ /views/mods/mod_klarna/order_done.phtml	(revision 8426)
@@ -0,0 +1,42 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 04.03.24
+	 * @time: 13:39
+	 */
+	
+	namespace wpsgKlarna;
+	
+	$view = $this->view['wpsg_mod_klarna'];
+	
+?>
+
+<div class="order_done_wpsg_mod_klarna <?php echo ($view['state']??''); ?>">
+
+	<?php if (($view['state']??'') === 'PAYED_DONE') { ?>
+	
+		<p><?php echo __('Betrag wurde mit Klarna bezahlt.', 'wpsgKlarna'); ?></p>
+	
+	<?php } else if (($view['state']??'') === 'PAYED') { ?>
+	
+		<p><?php echo __('Betrag wurde bereits mit Klarna bezahlt.', 'wpsgKlarna'); ?></p>
+
+	<?php } else if (($view['state']??'') === 'TOPAY') { ?>
+	
+		<div id="wpsg_mod_klarna_widget"></div>
+		<input type="button" class="button" id="klarna_payment_button" value="<?php echo __('Jetzt mit Klarna bezahlen.', 'wpsgKlarna'); ?>" />
+		
+		<?php
+		
+			$this->view['wpsg_mod_klarna']['button_id'] = 'klarna_payment_button';
+		
+			echo $this->render(dirname(__FILE__).'/pay.phtml');
+		
+		?>
+	
+	<?php } ?>
+
+</div>
Index: /views/mods/mod_klarna/order_view_afterpayment.phtml
===================================================================
--- /views/mods/mod_klarna/order_view_afterpayment.phtml	(revision 8426)
+++ /views/mods/mod_klarna/order_view_afterpayment.phtml	(revision 8426)
@@ -0,0 +1,31 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 04.03.24
+	 * @time: 16:38
+	 */
+	
+	namespace wpsgKlarna;
+	
+	$oOrder = \wpsg_order::getInstance(intval($this->view['data']['id']));
+	
+	$client_token = $oOrder->getMeta('wpsg_mod_klarna_client_token', false, '');
+	$session_id = $oOrder->getMeta('wpsg_mod_klarna_session_id', false, '');
+	$authorization_token = $oOrder->getMeta('wpsg_mod_klarna_authorization_token', false, '');
+	$klarna_order_id = $oOrder->getMeta('wpsg_mod_klarna_order_id', false, '');
+	$capture_id = $oOrder->getMeta('wpsg_mod_klarna_capture_id', false, '');
+
+?>
+
+<br />
+	
+<?php if ($client_token !== '') { echo wpsg_drawForm_Input('', __('Klarna ClientToken', 'wpsg'), $client_token, ['readonly' => true]);  } ?>
+<?php if ($session_id !== '') {  echo wpsg_drawForm_Input('', __('Klarna SessionID', 'wpsg'), $session_id, ['readonly' => true]); } ?>
+<?php if ($authorization_token !== '') {  echo wpsg_drawForm_Input('', __('Klarna AuthorizationToken', 'wpsg'), $authorization_token, ['readonly' => true]); } ?>
+<?php if ($klarna_order_id !== '') {  echo wpsg_drawForm_Input('', __('Klarna OrderId', 'wpsg'), $klarna_order_id, ['readonly' => true]); } ?>
+<?php if ($capture_id !== '') {  echo wpsg_drawForm_Input('', __('Klarna CaptureId', 'wpsg'), $capture_id, ['readonly' => true]); } ?>
+
+
Index: /views/mods/mod_klarna/pay.phtml
===================================================================
--- /views/mods/mod_klarna/pay.phtml	(revision 8426)
+++ /views/mods/mod_klarna/pay.phtml	(revision 8426)
@@ -0,0 +1,114 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 05.03.24
+	 * @time: 07:20
+	 */
+	
+	namespace wpsgKlarna;
+ 
+	$view = $this->view['wpsg_mod_klarna'];
+	
+	/** @var \wpsg_order $oOrder */
+	$oOrder = $view['oOrder'];
+	
+	$authorize_arg = [
+		'billing_address' => [
+			'given_name' => $oOrder->getInvoiceFirstName(),
+			'family_name' => $oOrder->getInvoiceName(),
+			'email' => $oOrder->getCustomer()->getEMail(),
+			'street_address' => $oOrder->getInvoiceStreet(),
+			'postal_code' => $oOrder->getInvoiceZip(),
+			'city' => $oOrder->getInvoiceCity(),
+		]
+	];
+	
+?>
+
+<script>
+	
+	window.klarnaAsyncCallback = () => {
+
+		const el_pppl_loading_blocker = document.getElementById('pppl_loading_blocker');
+		
+		Klarna.Payments.init({
+			client_token: '<?php echo $view['client_token']; ?>'
+		});
+		
+		Klarna.Payments.load({
+			container: '#wpsg_mod_klarna_widget'
+		}, {
+		
+		}, function (res) {
+
+			console.log(res);
+			
+		});
+		
+		document.getElementById('<?php echo $view['button_id']; ?>').addEventListener('click', (event) => {
+
+			event.preventDefault();
+			
+			if (el_pppl_loading_blocker) el_pppl_loading_blocker.style.display = 'block';
+			
+			Klarna.Payments.authorize(
+				{}, {},
+				function(res) {
+ 
+					console.log(res);
+				
+					if (res.authorization_token) {
+
+						try {
+ 
+							fetch('<?php echo $view['url_setAuthToken']; ?>', {
+								method: 'POST',
+								headers: {
+									"Content-Type": "application/json"
+								},
+								body: JSON.stringify({
+									'authorization_token': res.authorization_token
+								})
+							}).then(response => {
+
+								return response.json();
+
+							}).then(data => {
+
+								if (data.success) {
+
+									location.href = data.href;
+
+								} else throw Error();
+
+							}).catch(e => {
+
+								if (el_pppl_loading_blocker) el_pppl_loading_blocker.style.display = 'none';
+
+							});
+							
+						} catch (error) {
+
+							if (el_pppl_loading_blocker) el_pppl_loading_blocker.style.display = 'none';
+
+						}
+						
+					} else {
+						
+						if (el_pppl_loading_blocker) el_pppl_loading_blocker.style.display = 'none';
+						
+					}
+					
+				}
+			);
+
+		});
+
+	};
+	
+</script>
+
+<script src="https://x.klarnacdn.net/kp/lib/v1/api.js" async></script>
Index: /views/mods/mod_klarna/settings_edit.phtml
===================================================================
--- /views/mods/mod_klarna/settings_edit.phtml	(revision 8426)
+++ /views/mods/mod_klarna/settings_edit.phtml	(revision 8426)
@@ -0,0 +1,58 @@
+<?php
+	
+	declare(strict_types=1);
+	
+	/**
+	 * @author: daniel
+	 * @date: 04.03.24
+	 * @time: 11:56
+	 */
+	
+	namespace wpsgKlarna;
+	
+?>
+
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_active', __('Zahlungsart fÃŒr neue Bestellungen aktiv', 'wpsg'), $this->get_option('wpsg_mod_klarna_active'), ['help' => 'wpsg_mod_klarna_active']); ?>
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_admin_active', __('Zahlungsart nur fÃŒr Admins aktiv', 'wpsgPayone'), $this->get_option('wpsg_mod_klarna_admin_active'), ['help' => 'wpsg_mod_klarna_admin_active']); ?>
+
+<?php echo wpsg_drawForm_Input('wpsg_mod_klarna_api_user', __('API Benutzername', 'wpsg'), $this->get_option('wpsg_mod_klarna_api_user'), ['help' => 'wpsg_mod_klarna_api_user']); ?>
+<?php echo wpsg_drawForm_Input('wpsg_mod_klarna_api_password', __('API Passwort', 'wpsg'), $this->get_option('wpsg_mod_klarna_api_password'), ['help' => 'wpsg_mod_klarna_api_password']); ?>
+
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_sandbox', __('Sandbox Modus', 'wpsg'), $this->get_option('wpsg_mod_klarna_sandbox'), ['help' => 'wpsg_mod_klarna_sandbox']); ?>
+
+<div id="wpsg_mod_klarna_sandbox_layer">
+	<?php echo wpsg_drawForm_Input('wpsg_mod_klarna_sandbox_user', __('(Sandbox) API Benutzername', 'wpsg'), $this->get_option('wpsg_mod_klarna_sandbox_user'), ['help' => 'wpsg_mod_klarna_sandbox_user']); ?>
+	<?php echo wpsg_drawForm_Input('wpsg_mod_klarna_sandbox_password', __('(Sandbox) API Passwort', 'wpsg'), $this->get_option('wpsg_mod_klarna_sandbox_password'), ['help' => 'wpsg_mod_klarna_sandbox_password']); ?>
+</div>
+
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_debug', __('API Anfragen im Bestellprotokoll protokollieren', 'wpsg'), $this->get_option('wpsg_mod_klarna_debug'), ['help' => 'wpsg_mod_klarna_debug']); ?>
+
+<br />
+
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_checkout', __('Zahlungen im Checkout vorauthorisieren', 'wpsg'), $this->get_option('wpsg_mod_klarna_checkout'), array('help' => 'wpsg_mod_klarna_checkout')); ?>
+
+<br />
+
+<script>
+	
+	const el_wpsg_mod_klarna_sandbox = document.getElementById('wpsg_mod_klarna_sandbox');
+	const el_wpsg_mod_klarna_sandbox_layer = document.getElementById('wpsg_mod_klarna_sandbox_layer');
+	
+	el_wpsg_mod_klarna_sandbox.addEventListener('change', (event) => {
+		
+		if (event.target.checked) el_wpsg_mod_klarna_sandbox_layer.style.display = 'block';
+		else el_wpsg_mod_klarna_sandbox_layer.style.display = 'none';
+		
+	});
+	
+	el_wpsg_mod_klarna_sandbox.dispatchEvent(new Event('change'));
+	
+	
+</script>
+
+<br />
+
+<?php echo wpsg_drawForm_Input('wpsg_mod_klarna_fee', __('GebÃŒhr', 'wpsg'), wpsg_ff($this->get_option('wpsg_mod_klarna_fee'), true), array('help' => 'wpsg_mod_klarna_fee','unit' => $this->get_option('wpsg_currency').' / %')); ?>
+<?php echo wpsg_drawForm_Select('wpsg_mod_klarna_tax_key', __('Mehrwertsteuersatz', 'wpsg'), wpsg_tax_groups(), $this->get_option('wpsg_mod_klarna_tax_key'), array('help' => 'wpsg_mod_klarna_tax_key')); ?>
+<?php echo wpsg_drawForm_Checkbox('wpsg_mod_klarna_notaxcountry', __('Keine MwSt. wenn Land steuerfrei', 'wpsg'), $this->get_option('wpsg_mod_klarna_notaxcountry'), array('help' => 'wpsg_mod_klarna_notaxcountry')); ?>
+<?php echo wpsg_drawForm_Textarea('wpsg_mod_klarna_hint', __('Hinweistext', 'wpsg'), $this->get_option('wpsg_mod_klarna_hint'), array('help' => 'wpsg_mod_klarna_hint')); ?>
