Quellcode durchsuchen

feat(lakala): 新增交易查询功能并优化支付状态处理

- 在 QueryTradequeryRequest 中添加 jsonSerialize 返回类型声明
- 引入 QueryTradequeryApi 并在 TransactionService 中实现 queryTrade 方法
- 实现 PaymentProvider 的 query 方法以支持支付状态轮询
- 添加交易状态映射逻辑,支持触发支付成功事件
- 更新 TransactionServiceTest 增加 queryTrade 测试用例
- 使用 PHPUnit Attributes 标注测试方法
runphp vor 4 Monaten
Ursprung
Commit
ec92123ad1

+ 3 - 1
src/OpenAPISDK/V3/Model/QueryTradequeryRequest.php

@@ -12,6 +12,8 @@
 
 namespace SixShop\Lakala\OpenAPISDK\V3\Model;
 
+use PHPUnit\Framework\Attributes\Test;
+
 class QueryTradequeryRequest extends ModelRequest implements \JsonSerializable
 {
     // 商户号	M	String(32)	拉卡拉分配的商户号
@@ -82,7 +84,7 @@ class QueryTradequeryRequest extends ModelRequest implements \JsonSerializable
         return $invalidProperties;
     }
 
-    public function jsonSerialize()
+    public function jsonSerialize(): mixed
     {
         $this->setReqData([
             'merchant_no' => $this->merchantNo,

+ 29 - 6
src/PaymentProvider.php

@@ -17,12 +17,14 @@ use SixShop\Payment\Contracts\PaymentResponse;
 use SixShop\Payment\Entity\ExtensionPaymentEntity;
 use SixShop\Payment\Enum\PaymentBizEnum;
 use SixShop\Payment\Enum\PaymentStatusEnum;
+use SixShop\Payment\Event\PaymentSuccessEvent;
+use think\facade\Event;
 
 class PaymentProvider implements PaymentProviderInterface
 {
     public function __construct(
         private readonly Config $config,
-        private readonly ExtensionPaymentEntity $extensionPaymentEntity
+        private readonly ExtensionPaymentEntity $extensionPaymentEntity,
     )
     {
     }
@@ -72,12 +74,33 @@ class PaymentProvider implements PaymentProviderInterface
 
     #[\Override] public function query(int $recordID): PaymentQueryResult
     {
-        // todo 接口查询支付状态
+        $payment = $this->extensionPaymentEntity->read($recordID);
+        if ($payment->status === PaymentStatusEnum::PENDING) {
+            $response = TransactionService::queryTrade($payment->transaction_id);
+            // INIT-初始化 CREATE-下单成功 SUCCESS-交易成功 FAIL-交易失败 DEAL-交易处理中 UNKNOWN-未知状态 CLOSE-订单关闭 PART_REFUND-部分退款 REFUND-全部退款(或订单被撤销)
+            $payment->status = match ($response->trade_state) {
+                'DEAL' => PaymentStatusEnum::PENDING,
+                'SUCCESS' => PaymentStatusEnum::SUCCESS,
+                'FAIL' => PaymentStatusEnum::FAIL,
+                'CLOSE' => PaymentStatusEnum::CLOSED,
+                default => PaymentStatusEnum::PENDING,
+            };
+            if ($payment->status !== PaymentStatusEnum::PENDING) {
+                $payment->status_desc = $response->trade_state_desc;
+                if ($payment->status === PaymentStatusEnum::SUCCESS) {
+                    $payment->payment_time = time();
+                    $payment->save();
+                    Event::trigger(new PaymentSuccessEvent($payment['order_sn'], self::PAYMENT_TYPE, $payment->toArray(), $payment->biz_type));
+                } else {
+                    $payment->save();
+                }
+            }
+        }
         return new PaymentQueryResult(
-            orderNo: '',
-            status: PaymentStatusEnum::PENDING,
-            amount: 0,
-            raw: []
+            orderNo: $payment['out_trade_no'],
+            status: $payment['status'],
+            amount: (float)$payment['amount'],
+            raw: $payment->toArray()
         );
     }
 

+ 33 - 0
src/Service/TransactionService.php

@@ -2,8 +2,10 @@
 declare(strict_types=1);
 namespace SixShop\Lakala\Service;
 
+use SixShop\Lakala\OpenAPISDK\V3\Api\QueryTradequeryApi;
 use SixShop\Lakala\OpenAPISDK\V3\Api\TransPreorderApi;
 use SixShop\Lakala\OpenAPISDK\V3\Configuration;
+use SixShop\Lakala\OpenAPISDK\V3\Model\QueryTradequeryRequest;
 use SixShop\Lakala\OpenAPISDK\V3\Model\TradeAccBusiFields;
 use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaAccBusiFields;
 use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaDetail;
@@ -19,9 +21,12 @@ use function SixShop\Core\throw_logic_exception;
 class TransactionService
 {
     private TransPreorderApi $transPreorderApi;
+
+    private QueryTradequeryApi $queryTradequeryApi;
     public function __construct(private Config $config)
     {
         $this->transPreorderApi = new TransPreorderApi($config->getV3Config());
+        $this->queryTradequeryApi = new QueryTradequeryApi($config->getV3Config());
     }
 
     /**
@@ -86,4 +91,32 @@ class TransactionService
             );
         }
     }
+
+    /**
+     * 聚合扫码-交易查询
+     *
+     * 下单时的商户请求流水号 说明:out_trade_no、trade_no、必有其一。如果存在多个字段上送,优先级顺序如下: trade_no、 out_trade_no
+     *
+     * @param string $tradeNo 拉卡拉订单系统订单号
+     * @param string $outTradeNo 商户订单号
+     */
+    public function queryTrade(string $tradeNo = '', string $outTradeNo = ''):object
+    {
+        $request = new QueryTradequeryRequest();
+        $request->setMerchantNo($this->config->merchant_no);
+        $request->setTermNo($this->config->term_no);
+        $request->setTradeNo($tradeNo);
+        $request->setOutTradeNo($outTradeNo);
+        $response = $this->queryTradequeryApi->queryTradequery($request);
+
+        if ($response->getCode() == 'BBS00000') {
+            return $response->getRespData();
+        } else {
+            throw_logic_exception(
+                msg:$response->getMsg(),
+                status: $response->getCode(),
+                data: $response->getRespData(),
+            );
+        }
+    }
 }

+ 13 - 1
tests/Service/TransactionServiceTest.php

@@ -2,6 +2,7 @@
 
 namespace SixShop\Lakala\Service;
 
+use PHPUnit\Framework\Attributes\Test;
 use PHPUnit\Framework\TestCase;
 use SixShop\Lakala\Dto\LocationInfo;
 use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaAccBusiFields;
@@ -17,7 +18,8 @@ class TransactionServiceTest extends TestCase
         $this->transactionService = app(TransactionService::class);
     }
 
-    public function testPreOrder()
+    #[Test]
+    public function preOrder()
     {
         $totalAmount = 500;
         // 微信主扫场景 - 账户端业务信息
@@ -47,4 +49,14 @@ class TransactionServiceTest extends TestCase
         );
         dump($response);
     }
+
+    #[Test]
+    public function queryTrade()
+    {
+        $response = $this->transactionService->queryTrade(
+           // tradeNo: '20251119110113130266202252424725',
+            outTradeNo: '20251119145747020294',
+        );
+        dump($response);
+    }
 }