laowu 1 tydzień temu
rodzic
commit
61a2ea9a3e

+ 30 - 0
app/Http/logic/api/PayPlusLogic.php

@@ -172,6 +172,11 @@ class PayPlusLogic extends BaseApiLogic
         ];
 
         if ($this->isSuccessfulPayment($post)) {
+            if (!$this->confirmSuccessfulPayment($post)) {
+                Util::WriteLog('PayPlus', 'PayPlus order query not successful: ' . json_encode($post));
+                return 'success';
+            }
+
             $AdId = $order->AdId ?: '';
             $eventType = $order->eventType ?: '';
 
@@ -244,6 +249,31 @@ class PayPlusLogic extends BaseApiLogic
             && (int) ($post['data']['order_status'] ?? 0) === 3;
     }
 
+    public function confirmSuccessfulPayment(array $post)
+    {
+        $data = $post['data'] ?? [];
+        $platformOrderId = $data['platform_order_id'] ?? '';
+        if ($platformOrderId === '') {
+            return false;
+        }
+
+        try {
+            $result = $this->service->queryPayinOrder($platformOrderId, $data['order_id'] ?? '');
+        } catch (\Exception $exception) {
+            Util::WriteLog('PayPlus_error', 'PayPlus query order failed: ' . $exception->getMessage());
+            return false;
+        }
+
+        return $this->isSuccessfulPaymentQueryResult($result);
+    }
+
+    public function isSuccessfulPaymentQueryResult(array $result)
+    {
+        $data = $result['decryptedComponentDelta'] ?? ($result['data'] ?? $result);
+
+        return (int) ($data['order_status'] ?? 0) === 3;
+    }
+
     public function isFailedPayment(array $post)
     {
         $event = $post['event'] ?? '';

+ 22 - 2
app/Services/PayPlus.php

@@ -165,14 +165,34 @@ class PayPlus
     }
 
     public function postPayin(array $payload)
+    {
+        return $this->postPayinPath('/up-apis/merchant/payment', $payload);
+    }
+
+    public function queryPayinOrder($platformOrderId, $orderId = '')
+    {
+        $payload = [
+            'platform_order_id' => (string) $platformOrderId,
+        ];
+
+        if ($orderId !== '') {
+            $payload['order_id'] = (string) $orderId;
+        }
+
+        return $this->postPayinPath(
+            $this->config['query_path'] ?? '/up-apis/merchant/payment/query',
+            $payload
+        );
+    }
+
+    protected function postPayinPath($path, array $payload)
     {
         $encrypted = $this->encryptPayinPayload($payload);
         $response = $this->curlJson(
-            rtrim($this->config['apiUrl'] ?? '', '/') . '/up-apis/merchant/payment',
+            rtrim($this->config['apiUrl'] ?? '', '/') . $path,
             $encrypted['body'],
             $this->buildPayinHeaders()
         );
-        
 
         $decoded = json_decode($response, true) ?: [];
         Util::WriteLog('PayPlus', 'PayPlus raw response: ' . json_encode($decoded));

+ 1 - 0
config/pay.php

@@ -3,6 +3,7 @@
 return [
     'PayPlus' => [
         'apiUrl' => env('PAYPLUS_PAYIN_URL', ''),
+        'query_path' => env('PAYPLUS_QUERY_PATH', '/up-apis/merchant/payment/query'),
         'apiKey' => env('PAYPLUS_API_KEY', ''),
         'clientId' => env('PAYPLUS_CLIENT_ID', ''),
         'appId' => env('PAYPLUS_APP_ID', ''),

+ 1 - 0
config/payTest.php

@@ -92,6 +92,7 @@ return [
 
     'PayPlus' => [
         'apiUrl' => env('PAYPLUS_PAYIN_URL', 'https://pay-sandbox.payplus.net'),
+        'query_path' => env('PAYPLUS_QUERY_PATH', '/up-apis/merchant/payment/query'),
         'apiKey' => env('PAYPLUS_API_KEY', 'bPBYkV408FnADYDVJ4GlIHUB2CczfTiO'),
         'clientId' => env('PAYPLUS_CLIENT_ID', '3ebabd36-91a5-44cb-8ed9-5c3e49de5848'),
         'appId' => env('PAYPLUS_APP_ID', '104101'),

+ 73 - 2
tests/Unit/PayPlusLogicTest.php

@@ -37,8 +37,8 @@ class PayPlusLogicTest extends TestCase
         $this->assertSame('12.34', $payload['amount']);
         $this->assertSame(2, $payload['payment_method']);
         $this->assertSame('10001', $payload['account_info']['merchant_user_id']);
-        $this->assertSame('Nico', $payload['account_info']['first_name']);
-        $this->assertSame('Smith', $payload['account_info']['last_name']);
+        $this->assertSame('user', $payload['account_info']['first_name']);
+        $this->assertSame('user', $payload['account_info']['last_name']);
     }
 
     /** @test */
@@ -58,4 +58,75 @@ class PayPlusLogicTest extends TestCase
             'data' => ['order_status' => 4],
         ]));
     }
+
+    /** @test */
+    public function it_confirms_successful_notify_with_order_query()
+    {
+        $service = new FakePayPlusForPayinQuery([
+            'decryptedComponentDelta' => [
+                'order_status' => 3,
+                'event_detail_name' => 'payment_captured',
+            ],
+        ]);
+
+        $logic = new PayPlusLogic($service);
+
+        $this->assertTrue($logic->confirmSuccessfulPayment([
+            'event' => 'PAYMENT.CAPTURE.COMPLETED',
+            'event_detail_name' => 'payment_captured',
+            'data' => [
+                'platform_order_id' => 'P100',
+                'order_id' => 'O100',
+                'order_status' => 3,
+            ],
+        ]));
+
+        $this->assertSame('P100', $service->queriedPlatformOrderId);
+        $this->assertSame('O100', $service->queriedOrderId);
+    }
+
+    /** @test */
+    public function it_rejects_successful_notify_when_order_query_is_not_successful()
+    {
+        $service = new FakePayPlusForPayinQuery([
+            'decryptedComponentDelta' => [
+                'order_status' => 4,
+                'event_detail_name' => 'payment_declined',
+            ],
+        ]);
+
+        $logic = new PayPlusLogic($service);
+
+        $this->assertFalse($logic->confirmSuccessfulPayment([
+            'event' => 'PAYMENT.CAPTURE.COMPLETED',
+            'event_detail_name' => 'payment_captured',
+            'data' => [
+                'platform_order_id' => 'P100',
+                'order_id' => 'O100',
+                'order_status' => 3,
+            ],
+        ]));
+    }
+}
+
+class FakePayPlusForPayinQuery extends PayPlus
+{
+    public $queriedPlatformOrderId;
+    public $queriedOrderId;
+
+    private $queryResult;
+
+    public function __construct(array $queryResult)
+    {
+        parent::__construct([]);
+        $this->queryResult = $queryResult;
+    }
+
+    public function queryPayinOrder($platformOrderId, $orderId = '')
+    {
+        $this->queriedPlatformOrderId = $platformOrderId;
+        $this->queriedOrderId = $orderId;
+
+        return $this->queryResult;
+    }
 }