stanley-king 4 år sedan
förälder
incheckning
3cecaca15e

+ 3 - 3
data/config/dev/refill.ini.php

@@ -87,12 +87,12 @@ $config['oil_providers'] = $oil_providers;
 
 $baidu_phone = ['name' => 'baidu', 'store_id' => 8,
     'amount' => [
-        10 => [['goods_id' => 6245, 'price' => 9.51,  'card_type' => 'chinaunicom'],
-            ['goods_id' => 6245, 'price' => 9.81,  'card_type' => 'chinamobile']],
+        10 => [['goods_id' => 6245, 'price' => 9.51, 'quality' => 1, 'card_type' => 'chinaunicom'],
+               ['goods_id' => 6245, 'price' => 9.81, 'quality' => 2, 'card_type' => 'chinamobile']],
         20 => [['goods_id' => 6247, 'price' => 19.02, 'card_type' => 'chinaunicom,chinatelecom']],
         30 => [['goods_id' => 6249, 'price' => 28.53, 'card_type' => 'chinamobile,chinatelecom']],
         50 => [['goods_id' => 6250, 'price' => 47.55, 'card_type' => 'chinamobile,chinaunicom,chinatelecom']],
-        100 =>[['goods_id' => 6251, 'price' => 95.1, 'card_type' => 'chinamobile,chinaunicom,chinatelecom']]
+        100 => [['goods_id' => 6251, 'price' => 95.1, 'card_type' => 'chinamobile,chinaunicom,chinatelecom']]
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 $phone_providers = [

+ 9 - 0
helper/mtopcard/mtopcard.php

@@ -54,6 +54,15 @@ function topcard_type($str_type)
     elseif ($str_type == 'sinopec') { //中石化
         return SinopecCard;
     }
+    elseif ($str_type == 'chinamobile') { //中石化
+        return ChinaMobileCard;
+    }
+    elseif($str_type == 'chinaunicom') { //手机卡
+        return ChinaUnicomCard;
+    }
+    elseif($str_type == 'chinatelecom') { //手机卡
+        return ChinaTelecomCard;
+    }
     elseif($str_type == 'phone') { //手机卡
         return PhoneCard;
     }

+ 33 - 10
helper/refill/IRefill.php

@@ -2,7 +2,7 @@
 
 
 namespace refill;
-
+use mtopcard;
 
 abstract class IRefill
 {
@@ -10,8 +10,7 @@ abstract class IRefill
     protected $mStoreID;
     protected $mRefillType;
     protected $mOfficialSN;
-    protected $mCardType = [];
-    protected $mAmounts = [];
+    protected $mAmountTypes = [];
     protected $mPeriod;
     protected $mOpened;
     protected $mSort;
@@ -22,8 +21,29 @@ abstract class IRefill
         $this->mStoreID = $cfgs['store_id'];
         $this->mRefillType = $cfgs['refill_type'];
 
-        foreach ( $cfgs['amount'] as $k => $v) {
-            $this->mAmounts[$k] = $v;
+        $card_types = function ($stypes)
+        {
+            $result = [];
+            $types = explode(',',$stypes);
+            foreach ($types as $stype) {
+                $type = mtopcard\topcard_type($stype);
+                $result[] = $type;
+            }
+            return $result;
+        };
+
+
+        foreach ( $cfgs['amount'] as $spec => $items)
+        {
+            foreach ($items as $gitem)
+            {
+                $quality = $gitem['quality'] ?? 1;
+                $types = $card_types($gitem['card_type']);
+
+                foreach ($types as $type) {
+                    $this->mAmountTypes[$quality]["{$spec}-{$type}"] = ['goods_id' => $gitem['goods_id'],'price' => $gitem['price']];
+                }
+            }
         }
 
         $this->mPeriod = $cfgs['period'];
@@ -78,19 +98,22 @@ abstract class IRefill
 
     public function amounts()
     {
-        return $this->mAmounts;
+        return $this->mAmountTypes;
     }
 
-    public function goods(int $amout)
+    public function goods($quality,int $amount,int $card_type)
     {
-        if(array_key_exists($amout,$this->mAmounts)) {
-            $params = $this->mAmounts[$amout];
+        $maps = $this->mAmountTypes[$quality] ?? [];
+        $key = "{$amount}-{$card_type}";
+        if(array_key_exists($key,$maps)) {
+            $params = $maps[$key];
             return [$params['goods_id'], round($params['price'],2)];
         }
         else {
             return [];
         }
     }
+
     public function setOpened(bool $opened) {
         $this->mOpened = $opened;
     }
@@ -109,7 +132,7 @@ abstract class IRefill
 
     public function check(int $amount,int $card_type) : array
     {
-        if(!array_key_exists($amount,$this->mAmounts)) {
+        if(!array_key_exists($amount,$this->mAmountTypes)) {
             return [false,'额度不支持'];
         }
 

+ 2 - 0
helper/refill/LZRefillFactory.php

@@ -6,6 +6,8 @@ require_once(BASE_HELPER_PATH . '/refill/RefillBase.php');
 require_once(BASE_HELPER_PATH . '/refill/ProviderManager.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/IPolicy.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/lingzh/policy.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/lingzh/chctl.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/lingzh/ctl_item.php');
 
 use Log;
 use StatesHelper;

+ 103 - 103
helper/refill/ProviderManager.php

@@ -22,85 +22,114 @@ class ProviderManager
     protected $mPhoneProvider;
     protected $mProviderNames;
 
+    protected $mAllQMapPTS;
+    protected $mProviders;
+    protected $mSpecTypes;
+
     public function __construct()
     {
+
     }
 
-    public function load()
+    public function getQPTA()
     {
-        $this->mOilProvider = [];
-        $this->mPhoneProvider = [];
-        $this->mProviderNames = [];
-
-        global $config;
-        $oil_configs = $config['oil_providers'];
+        return $this->mAllQMapPTS;
+    }
 
-        $cfg_table = $this->read_channel();
+    private function map_cfg($cfgs,$refill_type)
+    {
+        $card_types = function ($stypes)
+        {
+            $result = [];
+            $types = explode(',',$stypes);
+            foreach ($types as $stype) {
+                $type = mtopcard\topcard_type($stype);
+                $result[] = $type;
+            }
+            return $result;
+        };
 
-        $names = [];
-        foreach ($oil_configs as $item)
+        $result = [];
+        foreach ($cfgs as $item)
         {
             $name = $item['name'];
             $cfg = $item['cfg'];
 
-            if(!array_key_exists($name,$cfg_table)) {
+            $provider = $this->create_provider($name,$cfg,$refill_type);
+            if($provider !== false) {
+                $this->mProviders[$name] = $provider;
+                $this->mProviderNames[] = $name;
+            } else {
                 continue;
             }
 
-            try {
-                $class = "refill\\{$name}\\RefillOil";
-                $table = $cfg_table[$name];
-
-                if (class_exists($class, false)) {
-                    $provider = new $class($cfg);
-                    $provider->setOpened($table['opened']);
-                    $provider->setSort($table['sort']);
-
-                    $names[] = $name;
-                    $this->mOilProvider[] = $provider;
-                } else {
-                    $error = "Base Error: class {$class} isn't exists!";
-                    throw new Exception($error);
+            $amounts = $cfg['amount'] ?? [];
+            foreach ($amounts as $spec => $goods)
+            {
+                foreach ($goods as $gitem)
+                {
+                    $quality = $gitem['quality'] ?? 1;
+
+                    $types = $card_types($gitem['card_type']);
+                    foreach ($types as $type) {
+                        $this->mAllQMapPTS[$quality]["{$name}-{$type}-{$spec}"] = ['goods_id' => $gitem['goods_id'],'price' => $gitem['price'],'provider' => $provider];
+                        $this->mSpecTypes[$quality]["{$type}-{$spec}"][] = $name;
+                    }
                 }
-            } catch (Exception $ex) {
-                Log::record($ex->getMessage(), Log::ERR);
             }
         }
 
-        $pho_configs = $config['phone_providers'];
-        foreach ($pho_configs as $item)
+        return $result;
+    }
+
+    private function create_provider($name,$cfg,$refill_type)
+    {
+        try
         {
-            $name = $item['name'];
-            $cfg = $item['cfg'];
+            $class = "refill\\{$name}\\{$refill_type}";
 
-            if(!array_key_exists($name,$cfg_table)) {
-                continue;
+            if (class_exists($class, false)) {
+                $provider = new $class($cfg);
+                $provider->setOpened(false);
+                return $provider;
+            } else {
+                $error = "Base Error: class {$class} isn't exists!";
+                Log::record(__FUNCTION__ . " {$error}", Log::ERR);
             }
+        }
+        catch (Exception $ex) {
+            Log::record($ex->getMessage(), Log::ERR);
+        }
+
+        return false;
+    }
+
+    public function load()
+    {
+        $this->mProviderNames = [];
+        $this->mAllQMapPTS = [];
+        $this->mProviders = [];
+        $this->mSpecTypes = [];
 
-            try {
-                $class = "refill\\{$name}\\RefillPhone";
-                $table = $cfg_table[$name];
+        global $config;
+        $this->map_cfg($config['phone_providers'],'RefillPhone');
+        $this->map_cfg($config['oil_providers'],'RefillOil');
+        $this->mProviderNames = array_unique($this->mProviderNames);
 
-                if (class_exists($class, false)) {
-                    $provider = new $class($cfg);
-                    $provider->setOpened($table['opened']);
-                    $provider->setSort($table['sort']);
-                    $names[] = $name;
+        $channels = $this->read_channel();
 
-                    $this->mPhoneProvider[] = $provider;
-                } else {
-                    $error = "Base Error: class {$class} isn't exists!";
-                    throw new Exception($error);
-                }
-            } catch (Exception $ex) {
-                Log::record($ex->getMessage(), Log::ERR);
+        foreach ($channels as $item)
+        {
+            $name = $item['name'];
+            $opened = $item['opened'] == 1 ? true : false;
+
+            if(array_key_exists($name,$this->mProviders)) {
+                $this->mProviders[$name]->setOpened($opened);
             }
         }
-
-        $this->mProviderNames = array_unique($names);
     }
 
-    public function read_channel()
+    private function read_channel()
     {
         $refill_provider = Model('refill_provider');
         $items = $refill_provider->getProviderList([]);
@@ -117,66 +146,37 @@ class ProviderManager
         return $result;
     }
 
-    public function find_providers(int $amount, int $card_type,int $quality): array
-    {
-        if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
-            return $this->find_oil($amount, $card_type);
-        } elseif ($card_type == mtopcard\ChinaMobileCard || $card_type == mtopcard\ChinaUnicomCard || $card_type == mtopcard\ChinaTelecomCard) {
-            return $this->find_phone($amount, $card_type);
-        } else {
-            return [];
-        }
-    }
-
-    public function provider(string $chname, int $card_type)
+    public function find_providers(int $spec, int $card_type,int $quality): array
     {
-        if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
-            $providers = $this->mOilProvider;
-        } elseif ($card_type == mtopcard\ChinaMobileCard || $card_type == mtopcard\ChinaUnicomCard || $card_type == mtopcard\ChinaTelecomCard) {
-            $providers = $this->mPhoneProvider;
-        } else {
-            return null;
-        }
-
-        foreach ($providers as $provider)
-        {
-            if ($provider->name() == $chname) {
-                return $provider;
+        $qnames = $this->mSpecTypes[$quality] ?? [];
+
+        $key = "{$card_type}-{$spec}";
+        if(array_key_exists($key,$qnames)) {
+            $names = $qnames[$key];
+
+            $providers = [];
+            foreach ($names as $name)
+            {
+                $provider = $this->mProviders[$name];
+                if($provider->opened()) {
+                    $providers[] = $provider;
+                }
             }
+            return $providers;
         }
-        return null;
-    }
-
-    private function find_oil(int $amount, int $card_type): array
-    {
-        $providers = [];
-        foreach ($this->mOilProvider as $provider) {
-            $name = $provider->name();
-            [$success, $err] = $provider->check($amount, $card_type);
-            if ($success) {
-                $providers[] = $provider;
-            } else {
-                Log::record("{$name} provider cannot match check,err:{$err}", Log::DEBUG);
-            }
+        else {
+            return [];
         }
-
-        return $providers;
     }
 
-    private function find_phone(int $amount, int $card_type): array
+    public function provider(string $chname)
     {
-        $providers = [];
-        foreach ($this->mPhoneProvider as $provider) {
-            $name = $provider->name();
-            [$success, $err] = $provider->check($amount, $card_type);
-            if ($success) {
-                $providers[] = $provider;
-            } else {
-                Log::record("{$name} provider cannot match check,err:{$err}", Log::DEBUG);
-            }
+        if(array_key_exists($chname,$this->mProviders)) {
+            return $this->mProviders[$chname];
+        }
+        else {
+            return null;
         }
-
-        return $providers;
     }
 
     public function combine_goods($configs,$type)

+ 2 - 3
helper/refill/RefillBase.php

@@ -229,7 +229,7 @@ class RefillBase
             $channel_name = $provider->name();
 
             //通道价格大于客户价格,换通道.
-            [$goods_id, $price] = $provider->goods($amount);
+            [$goods_id, $price] = $provider->goods($quality,$amount,$card_type);
             if ($price > $mch_amount) continue;
 
             $input['goods_id'] = $goods_id;
@@ -388,9 +388,8 @@ class RefillBase
         $refill_info = $mod_refill->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
 
         $chname = $refill_info['channel_name'];
-        $card_type = intval($refill_info['card_type']);
 
-        $provider = $this->mPolicy->provider($chname, $card_type);
+        $provider = $this->mPolicy->provider($chname);
         [$state, $order_state] = $provider->query($refill_info);
 
         if ($state === true)

+ 1 - 1
helper/refill/RefillFactory.php

@@ -17,7 +17,7 @@ class RefillFactory
             return LZRefillFactory::instance();
         }
         else {
-            return null;
+            return XYZRefillFactory::instance();
         }
     }
 }

+ 84 - 0
helper/refill/policy/lingzh/chctl.php

@@ -9,4 +9,88 @@ class chctl
 {
     protected $mSpeedtable;
 
+    static $cache_names = [
+        ['quality'=> 1,'name' => 'channel-ctl-oil-common-limit'],
+        ['quality'=> 2,'name' => 'channel-ctl-oil-fast-limit'],
+        ['quality'=> 1,'name' => 'channel-ctl-phone-common-limit'],
+        ['quality'=> 2,'name' => 'channel-ctl-phone-fast-limit']
+    ];
+
+    public function __construct()
+    {
+
+    }
+
+    public function load()
+    {
+        foreach (self::$cache_names as $cache)
+        {
+            $quality = $cache['quality'];
+            $cache_name = $cache['name'];
+            
+            $data = rcache($cache_name,"provider-");
+            $data = unserialize($data['data']);
+
+            $cfgs = $data ?? [];
+            foreach ($cfgs as $items)
+            {
+                foreach ($items as $item) {
+                    $name = $item['name'];
+                    $amount = $item['amount'];
+                    $card_type = $item['type'];
+
+                    $opened = $item['opened'] == 1 ? true : false;
+                    $sort = $item['sort'];
+                    $speed = $item['speed'];
+
+                    $key = $this->prefix($name,$amount,$card_type,$quality);
+                    $this->mSpeedtable[$key] = new ctl_item($name,$card_type,$amount,$speed,$sort,0,$opened);
+                }
+            }
+        }
+    }
+
+    public function match($names,int $spec, int $card_type,int $quality)
+    {
+        $ctl_items = [];
+        foreach ($names as $name) {
+            $key = $this->prefix($name,$spec,$card_type,$quality);
+            $ctl_items[] = $this->mSpeedtable[$key];
+        }
+
+        $usable_items = [];
+        foreach ($ctl_items as $item) {
+            if($item->opened()) {
+                $usable_items[] = $item;
+            }
+        }
+
+        $ascending = function ($l, $r) {
+            $lproity = $l->priority();
+            $rproity = $r->priority();
+
+            $lover = $l->speed_overload() ? 1 : 0;
+            $rover = $r->speed_overload() ? 1 : 0;
+
+            if($lover == $rover) {
+                return $lproity < $rproity ? -1 : 1;
+            }
+            else {
+                return $lover < $rover ? -1 : 1;
+            }
+        };
+        usort($usable_items, $ascending);
+
+        $result = [];
+        foreach ($usable_items as $item) {
+            $result[] = $item->name();
+        }
+
+        return $result;
+    }
+
+    private function prefix($name,$spec,$card_type,$quality)
+    {
+        return "{$name}-{$spec}-{$card_type}-{$quality}";
+    }
 }

+ 21 - 4
helper/refill/policy/lingzh/ctl_item.php

@@ -1,5 +1,8 @@
 <?php
 
+namespace refill;
+
+use Cache;
 
 class ctl_item
 {
@@ -19,13 +22,13 @@ class ctl_item
     private $mStorge;
     private $mOpened;
 
-    public function __construct($chname,$card_type,$amout,$max_speed,$priority,$storge,$opened)
+    public function __construct($chname,$card_type,$amount,$max_speed,$priority,$storge,$opened)
     {
-        $this->mPrefix = "speed-{$chname}-{$card_type}-{$amout}-";
+        $this->mPrefix = "speed-{$chname}-{$card_type}-{$amount}-";
 
         $this->mName = $chname;
         $this->mCardType = $card_type;
-        $this->mAmount = $amout;
+        $this->mAmount = $amount;
         $this->mMaxSpeed = $max_speed;
         $this->mPriority = $priority;
         $this->mStorge = $storge;
@@ -71,9 +74,17 @@ class ctl_item
     }
 
     public function speed_overload() : bool {
-        return $this->cur_speed() > $this->mMaxSpeed;
+        if($this->mMaxSpeed < 0) {
+            return false;
+        }
+        else {
+            return $this->cur_speed() > $this->mMaxSpeed;
+        }
     }
 
+    public function name() {
+        return $this->mName;
+    }
     public function priority() {
         return $this->mPriority;
     }
@@ -81,4 +92,10 @@ class ctl_item
     public function storge() {
         return $this->mStorge;
     }
+    public function opened() {
+        return $this->mOpened;
+    }
+    public function max_speed() {
+        return $this->mMaxSpeed;
+    }
 }

+ 35 - 2
helper/refill/policy/lingzh/policy.php

@@ -12,11 +12,44 @@ class policy extends ProviderManager implements IPolicy
     const high_times = 5;
     const high_time_out = 30;
 
-    public function find_providers(int $amount, int $card_type,int $quality): array
+    protected $mChannelControl;
+
+    public function __construct()
+    {
+        parent::__construct();
+        $this->mChannelControl = new chctl();
+    }
+
+
+    public function load()
+    {
+        parent::load();
+        $this->mChannelControl->load();
+    }
+
+
+    public function find_providers(int $spec, int $card_type,int $quality): array
     {
-        $providers = parent::find_providers($amount,$card_type,$quality);
+        $providers = parent::find_providers($spec,$card_type,$quality);
 
+        $names = [];
+        foreach ($providers as $provider) {
+            $names[] = $provider->name();
+        }
+        $names = $this->mChannelControl->match($names,$spec,$card_type,$quality);
+
+        $result = [];
+        foreach ($names as $name)
+        {
+            foreach ($providers as $provider)
+            {
+                if($name == $provider->name()) {
+                    $result[] = $provider;
+                }
+            }
+        }
 
+        return $result;
     }
 
     public function can_retry(array $refill_info, array $order_info): bool

+ 23 - 0
helper/refill/policy/xyz/policy.php

@@ -15,6 +15,29 @@ class policy extends ProviderManager implements IPolicy
     const high_times = 5;
     const high_time_out = 60;
 
+    public function find_providers(int $spec, int $card_type,int $quality): array
+    {
+        $providers = parent::find_providers($spec,$card_type,$quality);
+
+        $ascending = function ($l, $r) use ($quality,$spec,$card_type) {
+            [$glid, $lprice] = $l->goods($quality,$spec,$card_type);
+            [$rgid, $rprice] = $r->goods($quality,$spec,$card_type);
+
+            $lsort = $l->sort();
+            $rsort = $r->sort();
+
+            if($lprice == $rprice) {
+                return $lsort < $rsort ? -1 : 1;
+            }
+            else {
+                return $lprice < $rprice ? -1 : 1;
+            }
+        };
+        usort($providers, $ascending);
+
+        return $providers;
+    }
+
     public function can_retry(array $refill_info, array $order_info) : bool
     {
         $checker = function ($refill, $order)

+ 26 - 0
test/TestPolicy.php

@@ -0,0 +1,26 @@
+<?php
+
+
+use PHPUnit\Framework\TestCase;
+
+define('APP_ID', 'test');
+define('BASE_ROOT_PATH', str_replace('/test', '', dirname(__FILE__)));
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_CORE_PATH . '/lrlz.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_HELPER_PATH . '/queue/rdispatcher.php');
+require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+require_once(BASE_CORE_PATH . '/framework/function/http.php');
+
+class TestPolicy extends TestCase
+{
+    public static function setUpBeforeClass() : void
+    {
+        Base::run_util();
+    }
+    public function testLzPlicy()
+    {
+        $policy = new refill\policy();
+        $policy->load();
+    }
+}