Răsfoiți Sursa

feat(payment): 实现微信支付订单查询功能

- 新增 queryByOutTradeNo 方法用于通过商户订单号查询订单
- 完善 query 方法,实现订单状态更新和查询结果返回
- 优化 handleAsyncRequest 方法,增加错误处理逻辑
- 更新 composer 依赖,增加 six-shop/payment 包
runphp 6 luni în urmă
părinte
comite
18986a4e54
4 a modificat fișierele cu 43 adăugiri și 6 ștergeri
  1. 2 1
      composer.json
  2. 21 1
      src/PaymentProvider.php
  3. 14 0
      src/Trait/ApiTrait.php
  4. 6 4
      src/Trait/HandleAsyncRequestTrait.php

+ 2 - 1
composer.json

@@ -8,7 +8,8 @@
   ],
   "require": {
     "php": ">=8.3",
-    "six-shop/core": ">=0.4 <1.0",
+    "six-shop/payment": ">=0.1.6 <1.0",
+    "six-shop/core": ">=0.5.13 <1.0",
     "six-shop/wechat": "^0.1",
     "wechatpay/wechatpay": "^1.4.12"
   },

+ 21 - 1
src/PaymentProvider.php

@@ -3,6 +3,8 @@ declare(strict_types=1);
 
 namespace SixShop\WechatPay;
 
+use GuzzleHttp\Exception\ClientException;
+use SixShop\Core\Exception\NotFoundException;
 use SixShop\Core\Helper;
 use SixShop\Payment\Contracts\PaymentNotifyResult;
 use SixShop\Payment\Contracts\PaymentProviderInterface;
@@ -84,7 +86,25 @@ class PaymentProvider implements PaymentProviderInterface
 
     public function query(int $recordID): PaymentQueryResult
     {
-        throw new \Exception('Not implemented');
+        $payment = $this->extensionPaymentEntity->findOrEmpty($recordID);
+        if ($payment->status === PaymentStatusEnum::PENDING) {
+            try {
+                $payment->payment_result = $this->queryByOutTradeNo($payment['out_trade_no']);
+            } catch (ClientException $e) {
+                if ($e->getCode() === 404) {
+                    throw new NotFoundException(sprintf('订单%s不存在', $payment['out_trade_no']));
+                }
+                throw $e;
+            }
+            // todo 继续判断订单状态
+        }
+
+        return new PaymentQueryResult(
+            orderNo: $payment['out_trade_no'],
+            status: $payment['status'],
+            amount: $payment['amount'],
+            raw: $payment->toArray()
+        );
     }
 
     public function refund(array $refund): PaymentRefundResult

+ 14 - 0
src/Trait/ApiTrait.php

@@ -58,6 +58,20 @@ trait ApiTrait
 
     }
 
+    /**
+     * 商户订单号查询订单
+     */
+    private function queryByOutTradeNo(string $outTradeNo)
+    {
+        // https://pay.weixin.qq.com/doc/v3/merchant/4012791900
+        // 【GET】/v3/pay/transactions/out-trade-no/{out_trade_no}
+        return $this->handleAsyncRequest(function (BuilderChainable $builder, Config $config, string $outTradeNo): PromiseInterface {
+            return $builder->v3->pay->transactions->_out_trade_no_->getAsync([
+                'out_trade_no' => $outTradeNo,
+            ]);
+        }, $outTradeNo);
+    }
+
     /**
      * 退款申请
      *

+ 6 - 4
src/Trait/HandleAsyncRequestTrait.php

@@ -2,6 +2,7 @@
 declare(strict_types=1);
 namespace SixShop\WechatPay\Trait;
 
+use GuzzleHttp\Exception\RequestException;
 use GuzzleHttp\Promise\PromiseInterface;
 use SixShop\WechatPay\Facade\WechatPayBuilder;
 use think\exception\ErrorException;
@@ -22,10 +23,11 @@ trait HandleAsyncRequestTrait
                 return json_decode((string)$response->getBody());
             })
             ->otherwise(function ($e) {
-                if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
-
-                    $errorBody = json_decode((string)$e->getResponse()->getBody());
-                    throw new ErrorException(message: trim($errorBody->message));
+                if ($e instanceof RequestException && $e->hasResponse()) {
+                    if (json_validate((string)$e->getResponse()->getBody())) {
+                        $errorBody = json_decode((string)$e->getResponse()->getBody());
+                        throw new ErrorException(message: trim($errorBody->message));
+                    }
                 }
                 throw $e;
             })