Browse Source

添加安全校验

llp 1 day ago
parent
commit
0ca67cf3ae
1 changed files with 54 additions and 1 deletions
  1. 54 1
      packages/Longyi/Pay/Klarna/src/Payment/Klarna.php

+ 54 - 1
packages/Longyi/Pay/Klarna/src/Payment/Klarna.php

@@ -26,6 +26,7 @@ class Klarna extends Payment
     protected $currentInput;
     protected $createSessionUlr = 'https://api-na.playground.klarna.com/payments/v1/sessions';
     protected $createOrderUlr = 'https://api-na.playground.klarna.com/payments/v1/authorizations/{authorizationToken}/order';
+    protected $getOrderUlr = 'https://api-na.playground.klarna.com/ordermanagement/v1/orders/{order_id}';
 
     public function __construct(
         protected InvoiceRepository $invoiceRepository,
@@ -35,6 +36,7 @@ class Klarna extends Payment
         if ($this->getConfigData('mode') == 'live') {
             $this->createSessionUlr = 'https://api.klarna.com/payments/v1/sessions';
             $this->createOrderUlr = 'https://api.klarna.com/payments/v1/authorizations/{authorizationToken}/order';
+            $this->getOrderUlr = 'https://api.klarna.com/ordermanagement/v1/orders/{order_id}';
         }
         $this->clientId = $this->getConfigData('client_id');
         $this->apikey = $this->getConfigData('secret_id');
@@ -134,7 +136,16 @@ class Klarna extends Payment
         if (empty($resultObject->client_token)) {
             throw new \Exception('klarna api is error');
         }
-        return $resultObject->client_token;
+        // 生成 verify_token 并存入 order payment additional
+        $verifyToken = bin2hex(random_bytes(32));
+        if ($order->payment) {
+            $additional = $order->payment->additional ?? [];
+            $additional['klarna_verify_token'] = $verifyToken;
+            $additional['klarna_session_id']  = $resultObject->session_id ?? null;
+            $order->payment->additional = $additional;
+            $order->payment->save();
+        }
+        return $resultObject->client_token . '|' . $verifyToken;
     }
 
     /**
@@ -164,6 +175,12 @@ class Klarna extends Payment
         if ($order->status != Order::STATUS_PENDING) {
             return new \Exception('order status is error');
         }
+        $input = $this->getInput();
+        $verifyToken = $input->verifyToken ?? null;
+        $storedToken = $order->payment->additional['klarna_verify_token'] ?? null;
+        if (!$verifyToken || !$storedToken || !hash_equals($storedToken, $verifyToken)) {
+            throw new \Exception('klarna verify token is invalid');
+        }
         return $this->createOrder($order, $authorizationToken);
     }
 
@@ -222,6 +239,42 @@ class Klarna extends Payment
             throw new \Exception('klarna Create an order  is error');
         }
     }
+
+    public function fetchOrderStatus($gatewayOrderId = null)
+    {
+        $order = $this->getOrder();
+        if ($order) {
+            $gatewayOrderId = $order->payment->additional['transaction_id'];
+        }
+        if (empty($gatewayOrderId)) {
+            return new \Exception('OrderId is empty');
+        }
+        $client = new Client();
+        $response = $client->request('GET', str_replace('{order_id}', $gatewayOrderId, $this->getOrderUlr), [
+            'headers' => [
+                'Accept' => 'application/json',
+                'Content-Type' => 'application/json',
+                'Authorization' => 'Basic ' . base64_encode("{$this->clientId}:{$this->apikey}")
+            ],
+            'timeout' => 30,
+            'verify'  => false,
+        ]);
+        $responseBody = $response->getBody()->getContents();
+        Log::channel('payment')->info("klarna fetchOrderStatus response", [
+            'gatewayOrderId' => $gatewayOrderId,
+            'status' => $response->getStatusCode(),
+            'body' => $responseBody
+        ]);
+        $resultObject = json_decode($responseBody);
+        $paymentStatus = [];
+        $paymentStatus['captures'] = null;
+        $paymentStatus['status'] = null;
+        if ($resultObject->fraud_status == 'ACCEPTED' && $resultObject->status == 'AUTHORIZED') {
+            $paymentStatus['captures'] = true;
+            $paymentStatus['status'] = 'COMPLETED';
+        }
+        return $paymentStatus;
+    }
     /**
      * Get payment method image.
      *