瀏覽代碼

Merge branch 'rstanley' into raccount

stanley-king 1 年之前
父節點
當前提交
077e2f4c2e

+ 14 - 0
data/logic/queue.logic.php

@@ -1418,6 +1418,20 @@ class queueLogic
         }
     }
 
+    public function QueryAutoRefillState($params)
+    {
+        $order_id = intval($params['order_id']);
+        $query_times = intval($params['query_times']);
+
+        if($order_id <= 0) {
+            return callback(false, 'QueryAutoRefillState 参数order_id错误');
+        }
+        else {
+            refill\util::push_auto_query($order_id,$query_times);
+            return callback(true, '成功放入通知队列', ['order_id' => $order_id, 'query_times' => $query_times]);
+        }
+    }
+
     public function QueryOrderNeterr($params)
     {
         $order_id = intval($params['order_id']);

+ 94 - 2
helper/refill/RefillBase.php

@@ -536,9 +536,8 @@ class RefillBase
 
                 //如果对方没有回调能力,则启动主动查询.
                 if($provider->callback() === false) {
-                    QueueClient::async_push("QueryRefillState",['order_id' => $order_id],60);
+                    QueueClient::async_push("QueryAutoRefillState",['order_id' => $order_id,'query_times' => 0],3);
                 }
-
                 break;
             }
             else
@@ -895,6 +894,99 @@ class RefillBase
         return $ret;
     }
 
+    public function query_auto($order_id,$query_times)
+    {
+        $perioder = function ($times)
+        {
+            if($times > 10) {
+                return 300;
+            }
+            elseif($times > 5) {
+                return 120;
+            }
+            else {
+                return 5;
+            }
+        };
+
+        $query_handler = function ($order_id, $order_info, $state, $order_state, $chname,$order_time,$query_times) use ($perioder)
+        {
+            $query_times += 1;
+
+            $mod_refill = Model('refill_order');
+            $vr_part = util::part_vr_order(intval($order_info['add_time']));
+
+            $peroid = $perioder($query_times);
+
+            $can_try = false;
+            if (!$state) {
+                QueueClient::async_push("QueryAutoRefillState", ['order_id' => $order_id, 'query_times' => $query_times], $peroid);
+                $neterr = true;
+            } elseif ($order_state == ORDER_STATE_SUCCESS || $order_state == ORDER_STATE_CANCEL) {
+                $neterr = false;
+                QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
+            } elseif ($order_state == ORDER_STATE_NOEXIST) {
+                $neterr = false;
+                QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
+                $can_try = true;
+            } else {
+                $neterr = true;
+                QueueClient::async_push("QueryAutoRefillState", ['order_id' => $order_id, 'query_times' => $query_times], $peroid);
+            }
+
+            util::monitor_netchk($chname, $neterr);
+
+            return [true, $can_try];
+        };
+
+        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+        $mod_order = Model('vr_order');
+        $order_info = $mod_order->partition(util::part_notify())->getOrderInfo(['order_id' => $order_id]);
+        if (empty($order_info) || $order_info['order_state'] != ORDER_STATE_PAY) return false;
+
+        $mod_refill = Model('refill_order');
+        $refill_info = $mod_refill->partition(util::part_notify())->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
+
+        $chname = $refill_info['channel_name'];
+        $provider = $this->mPolicy->provider($chname);
+        if(empty($provider)) return false;
+
+        $values = $provider->query($refill_info);
+        if (count($values) == 2) {
+            [$state, $order_state] = $values;
+            $official_sn = false;
+        } else {
+            [$state, $order_state, $official_sn] = $values;
+        }
+
+        try {
+            $can_try = false;
+            $tran = new trans_wapper($mod_order, 'query_net change order state trans');
+            $order_info = $mod_order->partition(util::part_notify())->getOrderInfo(['order_id' => $order_id], '*', true, true);
+            $order_time = intval($refill_info['order_time']);
+            [$ret, $can_try] = $query_handler($order_id, $order_info, $state, $order_state, $chname,$order_time,$query_times);
+            $tran->commit();
+            $trans_succ = true;
+        }
+        catch (Exception $ex) {
+            Log::record("Error:" . $ex->getMessage(), Log::ERR);
+            $trans_succ = false;
+            $tran->rollback();
+            $ret = false;
+        }
+
+        if($can_try)
+        {
+            if($trans_succ) {
+                $this->proc_notify($order_id, false, true, $chname, $official_sn);
+            } else {
+                QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
+            }
+        }
+
+        return $ret;
+    }
+
     public function manual_success($order_id)
     {
         $order_id = intval($order_id);

+ 11 - 10
helper/refill/api/xyz/by_online/RefillCallBack.php

@@ -29,16 +29,17 @@ class RefillCallBack implements refill\IRefillCallBack
             return [false, false, false, false];
         }
         $order_id = $order_info['order_id'];
+        return [$order_id, false, false, false];
 
-        if ($status === 7) {
-            $data['official_sn'] = strtolower($params['charge_id']) == 'null' ? '' : $params['charge_id'];
-            Model('refill_order')->edit($order_id, $data);
-            QueueClient::async_push("QueryRefund", ['order_id' => $order_id], 3600);
-            return [$order_id, true, false, true];
-        } elseif (in_array($status, [3, 4, 6], true)) {
-            return [$order_id, false, true, true];
-        } else {
-            return [$order_id, false, false, false];
-        }
+//        if ($status === 7) {
+//            $data['official_sn'] = strtolower($params['charge_id']) == 'null' ? '' : $params['charge_id'];
+//            Model('refill_order')->edit($order_id, $data);
+//            QueueClient::async_push("QueryRefund", ['order_id' => $order_id], 3600);
+//            return [$order_id, true, false, true];
+//        } elseif (in_array($status, [3, 4, 6], true)) {
+//            return [$order_id, false, true, true];
+//        } else {
+//            return [$order_id, false, false, false];
+//        }
     }
 }

+ 89 - 61
helper/refill/api/xyz/by_online/RefillPhone.php

@@ -3,6 +3,7 @@
 namespace refill\by_online;
 
 require_once(BASE_HELPER_RAPI_PATH . '/by_online/config.php');
+require_once(BASE_HELPER_RAPI_PATH . '/by_online/hnyd.php');
 
 use refill;
 use Log;
@@ -15,6 +16,11 @@ class RefillPhone extends refill\IRefillPhone
         parent::__construct($cfgs);
     }
 
+    public function callback()
+    {
+        return false;
+    }
+
     private function req_params(int $phone, int $amount, int $card_type, string $order_sn, $regin_no)
     {
         $params['appId'] = config::APP_ID;
@@ -38,10 +44,6 @@ class RefillPhone extends refill\IRefillPhone
             return [false, '省份获取错误', false];
         }
 
-        if ($this->exist($card_no)) {
-            return [false, '今日已经提交过', false];
-        }
-
         $params = $this->req_params($card_no, $amount, $card_type, $params['order_sn'], $regin_no);
         $sign = config::sign($params);
         $params['sign'] = $sign;
@@ -51,12 +53,15 @@ class RefillPhone extends refill\IRefillPhone
 
         if (empty($resp)) {
             return [false, '系统错误', true];
-        } else {
+        }
+        else
+        {
             Log::record($resp, Log::DEBUG);
             $resp = json_decode($resp, true);
             if (empty($resp)) {
                 return [false, '系统错误', true];
             } elseif ($resp['code'] === 1000) {
+                Model()->table('refill_order')->where(['order_sn' => $params['order_sn']])->update(['official_sn' => $resp['data']['charge_id']]);
                 return [true, $resp['data']['order_sn'], false];
             } else {
                 return [false, $resp['msg'], false];
@@ -69,39 +74,97 @@ class RefillPhone extends refill\IRefillPhone
         $params['appId'] = config::APP_ID;
         $params['version'] = '1.0';
         $params['merchantOrderNo'] = $refill_info['order_sn'];
+        $params['is_HN'] = 2;
         $sign = config::sign($params);
         $params['sign'] = $sign;
 
+        $charge_id = $refill_info['official_sn'];
         $resp = http_request(config::QUERY_URL, $params);
-
         if (empty($resp)) {
             return [false, '网络错误', ''];
-        } else {
-            Log::record($resp, Log::DEBUG);
+        }
+        else
+        {
+            Log::record($resp,Log::DEBUG);
             $resp = json_decode($resp, true);
+
             if (empty($resp)) {
-                return [false, '网络错误'];
-            } elseif ($resp['code'] === 1000) {
-                $status = $resp['data']['order_status'];
-                if ($status === 7) {
-                    $updata['official_sn'] = $resp['data']['charge_id'];
-                    Model('refill_order')->edit($refill_info['order_id'], $updata);
-                    $order_state = ORDER_STATE_SUCCESS;
-                } elseif (in_array($status, [3, 4, 6], true)) {
-                    $order_state = ORDER_STATE_CANCEL;
-                } elseif (in_array($status, [0, 1, 2, 5], true)) {
-                    $order_state = ORDER_STATE_SEND;
-                } else {
-                    return [false, $status];
+                return [false, '网络错误', ''];
+            }
+            elseif($resp['code'] === 1000)
+            {
+                if(empty($resp['data'])) {
+                    return [false, '没有移动返回的原始数据', ''];
+                }
+                else
+                {
+                    ksort($resp);
+                    $response = new response($resp['data']);
+                    $record = $response->find_record($charge_id);
+                    if($record !== false)
+                    {
+                        if ($record->canceled()) {
+                            $order_state = ORDER_STATE_CANCEL;
+                        } elseif ($record->successed()) {
+                            $order_state = ORDER_STATE_SUCCESS;
+                            Model('refill_order')->edit($refill_info['order_id'], ['ch_trade_no' => $record->trade_id()]);
+                        } else {
+                            $order_state = ORDER_STATE_SEND;
+                        }
+
+                        return [true, $order_state, $charge_id];
+                    }
+                    elseif(time() - $refill_info['commit_time'] >= 2700) {
+                        return [true, ORDER_STATE_NOEXIST, $charge_id];
+                    }
+                    else {
+                        return [false, '没有移动返回的原始数据', ''];
+                    }
                 }
-
-                return [true, $order_state];
-            } else {
-                return [false, $resp['msg']];
+            }
+            else {
+                return [false, $resp['msg'], ''];
             }
         }
     }
 
+//    public function query($refill_info)
+//    {
+//        $params['appId'] = config::APP_ID;
+//        $params['version'] = '1.0';
+//        $params['merchantOrderNo'] = $refill_info['order_sn'];
+//        $sign = config::sign($params);
+//        $params['sign'] = $sign;
+//
+//        $resp = http_request(config::QUERY_URL, $params);
+//
+//        if (empty($resp)) {
+//            return [false, '网络错误', ''];
+//        } else {
+//            Log::record($resp, Log::DEBUG);
+//            $resp = json_decode($resp, true);
+//            if (empty($resp)) {
+//                return [false, '网络错误'];
+//            } elseif ($resp['code'] === 1000) {
+//                $status = $resp['data']['order_status'];
+//                if ($status === 7) {
+//                    $updata['official_sn'] = $resp['data']['charge_id'];
+//                    Model('refill_order')->edit($refill_info['order_id'], $updata);
+//                    $order_state = ORDER_STATE_SUCCESS;
+//                } elseif (in_array($status, [3, 4, 6], true)) {
+//                    $order_state = ORDER_STATE_CANCEL;
+//                } elseif (in_array($status, [0, 1, 2, 5], true)) {
+//                    $order_state = ORDER_STATE_SEND;
+//                } else {
+//                    return [false, $status];
+//                }
+//
+//                return [true, $order_state];
+//            } else {
+//                return [false, $resp['msg']];
+//            }
+//        }
+//    }
 
     public function balance()
     {
@@ -176,39 +239,4 @@ class RefillPhone extends refill\IRefillPhone
             }
         }
     }
-
-    public function query_origin($refill_info)
-    {
-        $params['appId'] = config::APP_ID;
-        $params['version'] = '1.0';
-        $params['merchantOrderNo'] = $refill_info['order_sn'];
-        $params['is_HN'] = 2;
-        $sign = config::sign($params);
-
-        $params['sign'] = $sign;
-
-        $resp = http_request(config::QUERY_URL, $params);
-
-        if (empty($resp)) {
-            return [false, true];
-        } else {
-            Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
-            if (empty($resp)) {
-                return [false, true];
-            } elseif ($resp['code'] === 1000) {
-                $status = $resp['data']['order_status'];
-                $succeed = $resp['data']['is_true'];
-
-                if ($status === 7 and $succeed === false) {
-                    return [true, false];
-                } else {
-                    return [false, false];
-                }
-            } else {
-                return [false, false];
-            }
-        }
-
-    }
-}
+}

+ 114 - 0
helper/refill/api/xyz/by_online/hnyd.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace refill\by_online;
+
+class record
+{
+    private $mRecord;
+    public function __construct($record)
+    {
+        $this->mRecord = $record;
+    }
+
+    public function charge_id() {
+        return trim($this->mRecord['CHARGE_ID']);
+    }
+
+    public function trade_id() {
+        return trim($this->mRecord['OUT_TRADE_ID']);
+    }
+
+    public function fee()
+    {
+        return intval($this->mRecord['RECV_FEE']);
+    }
+
+    public function charge_time()
+    {
+        if(empty($this->mRecord['RECV_TIME'])) {
+            return false;
+        } else {
+            return strtotime($this->mRecord['RECV_TIME']);
+        }
+    }
+
+    public function canceled()
+    {
+        $id = trim($this->mRecord['CANCEL_CHARGE_ID']);
+        if(empty($id)) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    public function successed()
+    {
+        $charge_time = $this->charge_time();
+        if(empty($this->charge_id()) or empty($this->trade_id()) or $this->fee() <= 0 or $charge_time=== false or $charge_time <= 0) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+
+class response
+{
+    private $mResult;
+    private $mRecords = [];
+    private $respCode;
+    public function __construct($resp)
+    {
+        $this->respCode = intval($resp['respCode']);
+        $this->mResult = $resp['result'];
+        ksort($this->mResult);
+
+        if(isset($this->mResult['data']))
+        {
+            $items = $this->mResult['data'];
+            foreach ( $items as $item)
+            {
+                ksort($item);
+                $this->mRecords[] = $item;
+            }
+            unset($this->mResult['data']);
+        }
+        else
+        {
+            $keys = [ "MONTH", "RECV_FEE", "RECV_TIME", "BIND_SERIAL_NUMBER",
+                "OUT_TRADE_ID", "GROUP_ID", "CHARGE_ID", "CANCEL_CHARGE_ID",
+                "CANCEL_TAG", "CANCEL_TIME", "REMARK", "LOCAL_SN", "CUST_NAME"];
+
+            $item = [];
+            foreach ($keys as $key) {
+                $item[$key] = $this->mResult[$key] ?? "";
+            }
+            ksort($item);
+            $this->mRecords[] = $item;
+            foreach ($keys as $key) {
+                unset($this->mResult[$key]);
+            }
+        }
+    }
+
+    public function find_record($charge_id)
+    {
+        foreach ($this->mRecords as $record)
+        {
+            $chid = $record['CHARGE_ID'];
+            if($chid == $charge_id) {
+                return new record($record);
+            }
+        }
+
+        return false;
+    }
+
+    public function record_count()
+    {
+        $count = intval($this->mResult['X_RECORDNUM'] ?? 0);
+        return $count;
+    }
+}

+ 11 - 0
helper/refill/util.php

@@ -322,6 +322,17 @@ class util
             return false;
         }
     }
+    public static function push_auto_query($order_id,$query_times)
+    {
+        try
+        {
+            $ret = self::push_queue('query_auto', ['order_id' => $order_id,'query_times' => $query_times]);
+            return $ret !== false;
+        }
+        catch (Exception $ex) {
+            return false;
+        }
+    }
 
     public static function push_query_net($order_id)
     {

+ 4 - 0
rdispatcher/processor.php

@@ -45,6 +45,10 @@ class processor extends queue\ILooper
                 } elseif ($method == 'query') {
                     $order_id = intval($params['order_id']);
                     $this->mProxy->query($order_id);
+                } elseif ($method == 'query_auto') {
+                    $order_id = intval($params['order_id']);
+                    $query_times = intval($params['query_times']);
+                    $this->mProxy->query_auto($order_id,$query_times);
                 } elseif ($method == 'query_net') {
                     $order_id = intval($params['order_id']);
                     $this->mProxy->query_net($order_id);

+ 5 - 0
rdispatcher/proxy.php

@@ -293,6 +293,11 @@ class proxy
     {
         return refill\RefillFactory::instance()->query($order_id);
     }
+
+    public function query_auto($order_id,$query_times)
+    {
+        return refill\RefillFactory::instance()->query_auto($order_id,$query_times);
+    }
     public function query_net($order_id)
     {
         return refill\RefillFactory::instance()->query_net($order_id);

+ 106 - 1
test/TestRefund.php

@@ -16,6 +16,8 @@ require_once(BASE_ROOT_PATH . '/global.php');
 require_once(BASE_CORE_PATH . '/lrlz.php');
 require_once(BASE_ROOT_PATH . '/fooder.php');
 require_once(BASE_ROOT_PATH . '/helper/order_helper.php');
+require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+require_once(BASE_CORE_PATH . '/framework/function/http.php');
 
 class TestRefund extends TestCase
 {
@@ -42,8 +44,111 @@ class TestRefund extends TestCase
         $helper->return_info('8000000000651001',10100,$err);
     }
 
+    //docker-compose run -d phpcli php /var/www/html/phpunit-9.2.5.phar --filter "/(TestRefund::testByOnline)( .*)?$/" --test-suffix TestRefund.php /var/www/html/test
     public function testByOnline()
     {
-        $x = 1;
+        $getProvider = function ($name, $type = 'RefillPhone')
+        {
+            $file = BASE_HELPER_RAPI_PATH . "/$name/{$type}.php";
+            if (!file_exists($file)) {
+                Log::record("provider api file=$file not exist.", Log::DEBUG);
+                return false;
+            } else {
+                require_once($file);
+                Log::record("file={$file} load success.", Log::DEBUG);
+            }
+
+            $class_name = "refill\\{$name}\\{$type}";
+            if (class_exists($class_name, false)) {
+                $caller = new $class_name([]);
+                return $caller;
+            }
+            else {
+                $error = "Base Error: class {$class_name} isn't exists!";
+                Log::record($error, Log::ERR);
+                return false;
+            }
+        };
+
+        $snmaker = function ()
+        {
+            return mt_rand(1000, 9999)
+                . sprintf('%010d', time())
+                . sprintf('%06d', (float)microtime() * 1000000);
+        };
+
+        $provider = $getProvider('by_online');
+        $order_sn = $snmaker();
+        Log::record("order_sn=$order_sn",Log::DEBUG);
+
+        $file = fopen(BASE_DATA_PATH . "/log/{$order_sn}.log",'a+');
+
+//        [$succ_add, $msg, $nerr] = $provider->add(18810246909, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+        [$succ_add, $msg, $nerr] = $provider->add(13911129867, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+//        [$succ_add, $msg, $nerr] = $provider->add(13925782928, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+//        [$succ_add, $msg, $nerr] = $provider->add(15120035568, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+//        [$succ_add, $msg, $nerr] = $provider->add(17801048874, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+//        [$succ_add, $msg, $nerr] = $provider->add(15951343795, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+//        [$succ_add, $msg, $nerr] = $provider->add(15064807655, 4, 1, ['regin_no' => 1, 'order_sn' => $order_sn]);
+        $last_tag = '';
+        $count = 0;
+        $commit_time = time();
+        while ($succ_add)
+        {
+            [$succ,$resp] = $provider->query(['order_sn' => $order_sn,'official_sn' => $nerr,'commit_time' => $commit_time]);
+            if($succ)
+            {
+                $tag = md5($resp);
+                if($tag != $last_tag) {
+                    fwrite($file,"md5=$tag\r\n");
+                    fwrite($file,$resp);
+                    fwrite($file,"\r\n");
+                    fflush($file);
+
+                    $last_tag = $tag;
+                } else {
+
+                    fwrite($file,"count=$count\r\n");
+                    fflush($file);
+                    $count += 1;
+                }
+            }
+            sleep(1);
+        }
+
+        fclose($file);
+    }
+
+    //docker-compose run -d phpcli php /var/www/html/phpunit-9.2.5.phar --filter "/(TestRefund::testByQuery)( .*)?$/" --test-suffix TestRefund.php /var/www/html/test
+    public function testByQuery()
+    {
+        $getProvider = function ($name, $type = 'RefillPhone')
+        {
+            $file = BASE_HELPER_RAPI_PATH . "/$name/{$type}.php";
+            if (!file_exists($file)) {
+                Log::record("provider api file=$file not exist.", Log::DEBUG);
+                return false;
+            } else {
+                require_once($file);
+                Log::record("file={$file} load success.", Log::DEBUG);
+            }
+
+            $class_name = "refill\\{$name}\\{$type}";
+            if (class_exists($class_name, false)) {
+                $caller = new $class_name([]);
+                return $caller;
+            }
+            else {
+                $error = "Base Error: class {$class_name} isn't exists!";
+                Log::record($error, Log::ERR);
+                return false;
+            }
+        };
+
+        $provider = $getProvider('by_online');
+
+        $order_sn = '94021685232830341599';
+//        $order_sn = '54821685230140381770';
+        [$succ, $resp] = $provider->query(['order_sn' => $order_sn, 'official_sn' => '1123052862339278']);
     }
 }