Просмотр исходного кода

Merge branch 'master' into dev

shizhongqi 21 часов назад
Родитель
Сommit
1969df68f8

+ 79 - 42
biz-ghs/lakala/services/LakalaAccountService.php

@@ -12,6 +12,7 @@ use common\components\lakala\LakalaOnboardingClient;
 use common\components\oss;
 use common\components\stringUtil;
 use common\components\util;
+use PhpAmqpLib\Wire\AMQPTable;
 use Yii;
 
 class LakalaAccountService
@@ -379,57 +380,93 @@ class LakalaAccountService
         if (empty($result)) {
             return $result;
         }
-        // 提交成功后按拉卡拉审核结果自动刷新,最多 3 次直到本地 APPROVED。
-        return self::refreshAfterPlatformSubmit(
-            $application->id,
-            $application->mainId,
-            $application->shopId,
-            $result
-        );
+        // 提交成功后延时 1 分钟刷新拉卡拉审核结果(最多 3 次),不阻塞本次审核提交。
+        self::scheduleRefreshAfterSubmit($application->id, $application->mainId, $application->shopId);
+        return $result;
     }
 
     /**
-     * 平台提交拉卡拉成功后,自动调用与客户端「刷新状态」相同的 refresh。
-     * 拉卡拉审核通过后回写商户号/终端;最多请求 3 次,直到 xhLakalaApplication.status=APPROVED。
-     * 拉卡拉驳回或刷新失败只记日志并返回已有提交结果,不阻断本次审核提交。
+     * 平台提交拉卡拉成功后,投递延时刷新消息(复用 limitBuyDelayExchange + stockConsumer)。
+     * 延时 1 分钟;消费失败或仍未终态时最多再投 2 次,共 3 次直到本地 APPROVED/REJECT。
      */
-    private static function refreshAfterPlatformSubmit($id, $mainId, $shopId, $fallback)
+    public static function scheduleRefreshAfterSubmit($id, $mainId, $shopId, $attempt = 1)
     {
-        $result = $fallback;
+        $id = intval($id);
+        $mainId = intval($mainId);
+        $shopId = intval($shopId);
+        $attempt = max(1, intval($attempt));
+        if ($id <= 0) {
+            return false;
+        }
+        try {
+            $message = serialize([
+                'type' => 'lakala_refresh',
+                'id' => $id,
+                'mainId' => $mainId,
+                'shopId' => $shopId,
+                'client' => 1,
+                'attempt' => $attempt,
+            ]);
+            $producer = Yii::$app->rabbitmq->getProducer('notifyProducer');
+            $producer->publish($message, 'limitBuyDelayExchange', 'lakalaRefreshDelayRoute', [
+                'delivery_mode' => 2,
+                'content_type' => 'application/octet-stream',
+                'application_headers' => new AMQPTable([
+                    'x-delay' => 60000,
+                ]),
+            ]);
+            Yii::info('lakala refresh delay: id=' . $id . ' attempt=' . $attempt, __METHOD__);
+        } catch (\Exception $e) {
+            Yii::error('Lakala scheduleRefreshAfterSubmit fail: ' . $e->getMessage(), __METHOD__);
+        }
+        return true;
+    }
+
+    /**
+     * 延时队列消费:调用与客户端「刷新状态」相同的 refresh。
+     * 拉卡拉驳回或刷新失败只记日志;未到终态且未满 3 次则再延时 1 分钟。
+     */
+    public static function handleDelayedRefresh($data)
+    {
+        $id = intval($data['id'] ?? 0);
+        $mainId = intval($data['mainId'] ?? 0);
+        $shopId = intval($data['shopId'] ?? 0);
+        $attempt = max(1, intval($data['attempt'] ?? 1));
         $maxAttempts = 3;
-        $retryInterval = 3;
-        for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
-            try {
-                $application = LakalaApplicationClass::getById($id, true);
-                if (empty($application)) {
-                    return $result;
-                }
-                // 已认证通过则无需再刷;拉卡拉已驳回也不会变成 APPROVED,停止重试。
-                if ($application->status === LakalaApplicationClass::STATUS_APPROVED
-                    || $application->status === LakalaApplicationClass::STATUS_REJECT) {
-                    return $result;
-                }
-                // 没有拉卡拉查询主键时 refresh 会直接失败退出,提交后若尚未回写则跳过。
-                $canRefresh = $application->type === LakalaApplicationClass::TYPE_SETTLEMENT_CHANGE
-                    ? !empty($application->reviewRelatedId)
-                    : (!empty($application->customerNo) || !empty($application->merchantNo));
-                if (!$canRefresh) {
-                    return $result;
-                }
-                $result = self::refresh($application->id, $application->mainId, $application->shopId);
-                $application = LakalaApplicationClass::getById($id, true);
-                if (!empty($application) && ($application->status === LakalaApplicationClass::STATUS_APPROVED
-                    || $application->status === LakalaApplicationClass::STATUS_REJECT)) {
-                    return $result;
-                }
-            } catch (\Throwable $e) {
-                Yii::warning('Lakala platformApprove auto refresh attempt ' . $attempt . ' failed: ' . $e->getMessage());
+        try {
+            $application = LakalaApplicationClass::getById($id, true);
+            if (empty($application)) {
+                return true;
             }
-            if ($attempt < $maxAttempts) {
-                sleep($retryInterval);
+            if ($mainId <= 0) {
+                $mainId = intval($application->mainId);
+            }
+            if ($shopId <= 0) {
+                $shopId = intval($application->shopId);
+            }
+            if ($application->status === LakalaApplicationClass::STATUS_APPROVED
+                || $application->status === LakalaApplicationClass::STATUS_REJECT) {
+                return true;
+            }
+            $canRefresh = $application->type === LakalaApplicationClass::TYPE_SETTLEMENT_CHANGE
+                ? !empty($application->reviewRelatedId)
+                : (!empty($application->customerNo) || !empty($application->merchantNo));
+            if (!$canRefresh) {
+                return true;
             }
+            self::refresh($application->id, $application->mainId, $application->shopId);
+            $application = LakalaApplicationClass::getById($id, true);
+            if (!empty($application) && ($application->status === LakalaApplicationClass::STATUS_APPROVED
+                || $application->status === LakalaApplicationClass::STATUS_REJECT)) {
+                return true;
+            }
+        } catch (\Throwable $e) {
+            Yii::warning('Lakala delayed refresh attempt ' . $attempt . ' failed: ' . $e->getMessage());
         }
-        return $result;
+        if ($attempt < $maxAttempts && $id > 0) {
+            self::scheduleRefreshAfterSubmit($id, $mainId, $shopId, $attempt + 1);
+        }
+        return true;
     }
 
     public static function refresh($id, $mainId, $shopId)

+ 79 - 42
biz-hd/lakala/services/LakalaAccountService.php

@@ -13,6 +13,7 @@ use common\components\noticeUtil;
 use common\components\oss;
 use common\components\stringUtil;
 use common\components\util;
+use PhpAmqpLib\Wire\AMQPTable;
 use Yii;
 
 /**
@@ -382,57 +383,93 @@ class LakalaAccountService
         if (empty($result)) {
             return $result;
         }
-        // 提交成功后按拉卡拉审核结果自动刷新,最多 3 次直到本地 APPROVED。
-        return self::refreshAfterPlatformSubmit(
-            $application->id,
-            $application->mainId,
-            $application->shopId,
-            $result
-        );
+        // 提交成功后延时 1 分钟刷新拉卡拉审核结果(最多 3 次),不阻塞本次审核提交。
+        self::scheduleRefreshAfterSubmit($application->id, $application->mainId, $application->shopId);
+        return $result;
     }
 
     /**
-     * 平台提交拉卡拉成功后,自动调用与客户端「刷新状态」相同的 refresh。
-     * 拉卡拉审核通过后回写商户号/终端;最多请求 3 次,直到 xhLakalaApplication.status=APPROVED。
-     * 拉卡拉驳回或刷新失败只记日志并返回已有提交结果,不阻断本次审核提交。
+     * 平台提交拉卡拉成功后,投递延时刷新消息(复用 limitBuyDelayExchange + stockConsumer)。
+     * 延时 1 分钟;消费失败或仍未终态时最多再投 2 次,共 3 次直到本地 APPROVED/REJECT。
      */
-    private static function refreshAfterPlatformSubmit($id, $mainId, $shopId, $fallback)
+    public static function scheduleRefreshAfterSubmit($id, $mainId, $shopId, $attempt = 1)
     {
-        $result = $fallback;
+        $id = intval($id);
+        $mainId = intval($mainId);
+        $shopId = intval($shopId);
+        $attempt = max(1, intval($attempt));
+        if ($id <= 0) {
+            return false;
+        }
+        try {
+            $message = serialize([
+                'type' => 'lakala_refresh',
+                'id' => $id,
+                'mainId' => $mainId,
+                'shopId' => $shopId,
+                'client' => self::CLIENT,
+                'attempt' => $attempt,
+            ]);
+            $producer = Yii::$app->rabbitmq->getProducer('notifyProducer');
+            $producer->publish($message, 'limitBuyDelayExchange', 'lakalaRefreshDelayRoute', [
+                'delivery_mode' => 2,
+                'content_type' => 'application/octet-stream',
+                'application_headers' => new AMQPTable([
+                    'x-delay' => 60000,
+                ]),
+            ]);
+            Yii::info('lakala refresh delay: id=' . $id . ' attempt=' . $attempt, __METHOD__);
+        } catch (\Exception $e) {
+            Yii::error('Lakala scheduleRefreshAfterSubmit fail: ' . $e->getMessage(), __METHOD__);
+        }
+        return true;
+    }
+
+    /**
+     * 延时队列消费:调用与客户端「刷新状态」相同的 refresh。
+     * 拉卡拉驳回或刷新失败只记日志;未到终态且未满 3 次则再延时 1 分钟。
+     */
+    public static function handleDelayedRefresh($data)
+    {
+        $id = intval($data['id'] ?? 0);
+        $mainId = intval($data['mainId'] ?? 0);
+        $shopId = intval($data['shopId'] ?? 0);
+        $attempt = max(1, intval($data['attempt'] ?? 1));
         $maxAttempts = 3;
-        $retryInterval = 3;
-        for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
-            try {
-                $application = LakalaApplicationClass::getById($id, true);
-                if (empty($application)) {
-                    return $result;
-                }
-                // 已认证通过则无需再刷;拉卡拉已驳回也不会变成 APPROVED,停止重试。
-                if ($application->status === LakalaApplicationClass::STATUS_APPROVED
-                    || $application->status === LakalaApplicationClass::STATUS_REJECT) {
-                    return $result;
-                }
-                // 没有拉卡拉查询主键时 refresh 会直接失败退出,提交后若尚未回写则跳过。
-                $canRefresh = $application->type === LakalaApplicationClass::TYPE_SETTLEMENT_CHANGE
-                    ? !empty($application->reviewRelatedId)
-                    : (!empty($application->customerNo) || !empty($application->merchantNo));
-                if (!$canRefresh) {
-                    return $result;
-                }
-                $result = self::refresh($application->id, $application->mainId, $application->shopId);
-                $application = LakalaApplicationClass::getById($id, true);
-                if (!empty($application) && ($application->status === LakalaApplicationClass::STATUS_APPROVED
-                    || $application->status === LakalaApplicationClass::STATUS_REJECT)) {
-                    return $result;
-                }
-            } catch (\Throwable $e) {
-                Yii::warning('Lakala platformApprove auto refresh attempt ' . $attempt . ' failed: ' . $e->getMessage());
+        try {
+            $application = LakalaApplicationClass::getById($id, true);
+            if (empty($application)) {
+                return true;
             }
-            if ($attempt < $maxAttempts) {
-                sleep($retryInterval);
+            if ($mainId <= 0) {
+                $mainId = intval($application->mainId);
+            }
+            if ($shopId <= 0) {
+                $shopId = intval($application->shopId);
+            }
+            if ($application->status === LakalaApplicationClass::STATUS_APPROVED
+                || $application->status === LakalaApplicationClass::STATUS_REJECT) {
+                return true;
+            }
+            $canRefresh = $application->type === LakalaApplicationClass::TYPE_SETTLEMENT_CHANGE
+                ? !empty($application->reviewRelatedId)
+                : (!empty($application->customerNo) || !empty($application->merchantNo));
+            if (!$canRefresh) {
+                return true;
             }
+            self::refresh($application->id, $application->mainId, $application->shopId);
+            $application = LakalaApplicationClass::getById($id, true);
+            if (!empty($application) && ($application->status === LakalaApplicationClass::STATUS_APPROVED
+                || $application->status === LakalaApplicationClass::STATUS_REJECT)) {
+                return true;
+            }
+        } catch (\Throwable $e) {
+            Yii::warning('Lakala delayed refresh attempt ' . $attempt . ' failed: ' . $e->getMessage());
         }
-        return $result;
+        if ($attempt < $maxAttempts && $id > 0) {
+            self::scheduleRefreshAfterSubmit($id, $mainId, $shopId, $attempt + 1);
+        }
+        return true;
     }
 
     public static function refresh($id, $mainId, $shopId)

+ 13 - 0
common/components/rabbitmq/stockConsumer.php

@@ -9,6 +9,8 @@ namespace common\components\rabbitmq;
 use bizGhs\product\classes\ProductClass;
 use bizHd\birthday\classes\BirthdayGiftClass;
 use bizHd\groupBuy\classes\GroupBuyClass;
+use bizHd\lakala\services\LakalaAccountService as HdLakalaAccountService;
+use bizGhs\lakala\services\LakalaAccountService as GhsLakalaAccountService;
 use bizHd\product\classes\ProductClass as hdProductClass;
 use common\components\noticeUtil;
 use mikemadisonweb\rabbitmq\components\ConsumerInterface;
@@ -69,6 +71,17 @@ class stockConsumer extends baseConsumer
                         return GroupBuyClass::expireById($groupBuyId);
                     });
                     break;
+                case 'lakala_refresh':
+                    $applicationId = intval($data['id']);
+                    $client = intval($data['client']);
+                    echo 'lakala_refresh --- id=' . $applicationId . ' client=' . $client;
+                    $result = $this->runWithDbReconnect(function () use ($data, $client) {
+                        if ($client === 2) {
+                            return HdLakalaAccountService::handleDelayedRefresh($data);
+                        }
+                        return GhsLakalaAccountService::handleDelayedRefresh($data);
+                    });
+                    break;
                 default:
                     noticeUtil::push("库存的消费者报错,未知 type: {$type}");
                     $result = false;

+ 11 - 0
common/config/rabbitMQ.php

@@ -86,6 +86,11 @@ $rabbitMQ = [
             'passive' => false,
             'durable' => true,
         ],
+        [
+            'name' => 'lakalaRefreshQueue',
+            'passive' => false,
+            'durable' => true,
+        ],
     ],
 
     /**
@@ -128,6 +133,11 @@ $rabbitMQ = [
             'exchange' => 'limitBuyDelayExchange',
             'routing_keys' => ['groupBuyDelayRoute'],
         ],
+        [
+            'queue' => 'lakalaRefreshQueue',
+            'exchange' => 'limitBuyDelayExchange',
+            'routing_keys' => ['lakalaRefreshDelayRoute'],
+        ],
     ],
 
     /**
@@ -172,6 +182,7 @@ $rabbitMQ = [
                 'limitBuyQueue' => '\common\components\rabbitmq\stockConsumer',
                 'birthdayGiftQueue' => '\common\components\rabbitmq\stockConsumer', //生日礼物队列
                 'groupBuyQueue' => '\common\components\rabbitmq\stockConsumer', //拼团到期队列
+                'lakalaRefreshQueue' => '\common\components\rabbitmq\stockConsumer', //拉卡拉进件刷新队列
             ]
         ],
         [