Przeglądaj źródła

feat(payment): 添加微信支付退款查询功能

- 在 PaymentProvider 中实现 refundQuery 方法,支持查询退款状态
- 添加 queryRefund 私有方法,用于调用微信支付退款查询接口
- 更新 ExtensionRefundModel,增加与 ExtensionPaymentModel 的关联关系
- 移除 sixshop-payment 扩展的冗余信息,简化配置
- 新增 PaymentProviderTest 单元测试用例,验证退款查询功能
runphp 6 miesięcy temu
rodzic
commit
ad4da3cada

+ 20 - 1
src/PaymentProvider.php

@@ -19,6 +19,7 @@ use SixShop\Payment\Enum\PaymentBizEnum;
 use SixShop\Payment\Enum\PaymentStatusEnum;
 use SixShop\Payment\Enum\RefundStatusEnum;
 use SixShop\Payment\Event\PaymentSuccessEvent;
+use SixShop\Payment\Event\RefundSuccessEvent;
 use SixShop\Wechat\Facade\WechatUser;
 use SixShop\WechatPay\Trait\ApiTrait;
 use SixShop\WechatPay\Trait\PaymentParamsTrait;
@@ -133,6 +134,7 @@ class PaymentProvider implements PaymentProviderInterface
                 'reason' => $param->getReason(),
                 'amount' => $param->getAmount(),
                 'status' => RefundStatusEnum::REFUNDING,
+                'refund_param' => $param->getRaw(),
                 'status_desc' => '正在申请微信接口退款',
             ]);
             $this->domesticRefunds(
@@ -149,6 +151,23 @@ class PaymentProvider implements PaymentProviderInterface
 
     public function refundQuery(int $refundID): PaymentRefundResult
     {
-        throw new \Exception('Not implemented');
+        $refund = $this->extensionRefundEntity->with('payment')->find($refundID);
+        if ($refund->status === RefundStatusEnum::REFUNDING) {
+            $result = $this->queryRefund($refund->out_refund_no);
+            $refund->refund_id = $result->refund_id;
+            $refund->refund_result = $result;
+            if ($result->status === 'SUCCESS') {
+                $refund->status = RefunddStatusEnum::SUCCESS;
+                $refund->success_time = strtotime($result->success_time);
+                Event::trigger(new RefundSuccessEvent(
+                        $refund->model(),
+                        $refund->payment,
+                        new PaymentRefundRequest($refund->amount,$refund->reason, $refund->refund_param))
+                );
+            }
+            $refund->save();
+        }
+
+        return new PaymentRefundResult($refund->model());
     }
 }

+ 11 - 0
src/Trait/ApiTrait.php

@@ -98,6 +98,17 @@ trait ApiTrait
         }, $outRefundNo, $outTradeNo, $refund, $total, $reason);
     }
 
+    private function queryRefund(string $outRefundNo)
+    {
+        // https://pay.weixin.qq.com/doc/v3/merchant/4012791863
+        // 【GET】/v3/refund/domestic/refunds/{out_refund_no}
+        return $this->handleAsyncRequest(function (BuilderChainable $builder, Config $config, string $outRefundNo): PromiseInterface {
+            return $builder->v3->refund->domestic->refunds->_out_refund_no_->getAsync([
+                'out_refund_no' => $outRefundNo,
+            ]);
+        }, $outRefundNo);
+    }
+
     /**
      * 发起转账
      *

+ 24 - 0
test/PaymentProviderTest.php

@@ -0,0 +1,24 @@
+<?php
+declare(strict_types=1);
+namespace SixShop\WechatPay;
+
+use app\admin\listener\RefundSuccessListener;
+use PHPUnit\Framework\TestCase;
+use SixShop\Payment\Contracts\PaymentRefundResult;
+use SixShop\Payment\Event\RefundSuccessEvent;
+
+class PaymentProviderTest extends TestCase
+{
+    private PaymentProvider $provider;
+    protected function setUp(): void
+    {
+        $this->provider = app()->make(PaymentProvider::class);
+    }
+
+    public function testRefundQuery():void
+    {
+        app()->event->listen(RefundSuccessEvent::class, RefundSuccessListener::class);
+        $result = $this->provider->refundQuery(15);
+        $this->assertInstanceOf(PaymentRefundResult::class, $result);
+    }
+}

+ 6 - 0
test/WechatPayBuilderTest.php

@@ -40,4 +40,10 @@ class WechatPayBuilderTest extends TestCase
         $result = $this->queryByOutTradeNo('20250904133148020905');
         dump($result);
     }
+
+    public function testQueryRefund()
+    {
+        $result = $this->queryRefund('20250909135117037302');
+        dump($result);
+    }
 }