瀏覽代碼

wantong merge

ayHaru 4 年之前
父節點
當前提交
b79a22f99d

+ 1 - 1
admin/templates/default/css/recharge.css

@@ -61,7 +61,7 @@
 .provider_amount_control #tableHread th,
 .provider_amount_control #tableHread td{ background-color: #fff;}
 .provider_amount_control #tableHread  { position: fixed;top:138px;left:20px;background-color: #fff;z-index:999;width: 96.5%;}
-.provider_amount_control .batch-td { text-align: center;width: 160px;min-width:160px;padding-right: 10px;}
+.provider_amount_control .batch-td { text-align: center;width: 150px;min-width:150px;padding-right: 10px;}
 .provider_amount_control .batch-td .listNum { width: 51px;display:inline-block;}
 .provider_amount_control .batch-td .priority { width: 45px;display:inline-block;}
 /* 提示边框 */

+ 1 - 1
admin/templates/default/provider.amount.control.php

@@ -1,4 +1,4 @@
-<link href="<?php echo ADMIN_TEMPLATES_URL;?>/css/recharge.css?7" rel="stylesheet" type="text/css" id="cssfile2" />
+<link href="<?php echo ADMIN_TEMPLATES_URL;?>/css/recharge.css?2" rel="stylesheet" type="text/css" id="cssfile2" />
 <?php defined('InShopNC') or exit('Access Invalid!'); ?>
 <div class="page provider_amount_control">
     <div class="fixed-bar">

+ 30 - 10
docker/compose/stanley/docker-compose.yml

@@ -189,13 +189,33 @@ services:
       - "websrv"
       - "searcher"
 
-#  async:
-#    image: php-swool-redis:latest
-#    volumes:
-#      - ../../conf/etc/localtime:/etc/localtime:ro
-#      - ../../conf/php/php-swoole-debug.ini:/usr/local/etc/php/php.ini
-#      - ../../../:/var/www/html
-#      - /Volumes/Transcend/upload:/var/www/html/data/upload
-#      - /Users/stanley-king/work/PHPProject/shoplog:/var/www/html/data/log
-#    container_name: "panda-async"
-#    command: [php, "/var/www/html//test/examples/process/async_master.php"]
+  flasksrv:
+    image: pycpu:3.7.10
+    ports:
+      - "5000:5000"
+    volumes:
+      - ../../conf/etc/localtime:/etc/localtime:ro
+      - ../../../:/var/www/html
+      - /Users/stanley-king/work/PHPProject/shoplog:/var/www/html/data/log
+      - /Users/stanley-king/work/PHPProject/stdata:/var/www/html/data/stdata
+    container_name: "panda-flask"
+    command: ['python','app.py']
+
+  pythoncli:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../conf/etc/localtime:/etc/localtime:ro
+      - ../../../:/var/www/html
+      - /Users/stanley-king/work/PHPProject/shoplog:/var/www/html/data/log
+      - /Users/stanley-king/work/PHPProject/stdata:/var/www/html/data/stdata
+    container_name: "panda-python"
+
+  readersrv:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../conf/etc/localtime:/etc/localtime:ro
+      - ../../../:/var/www/html
+      - /Users/stanley-king/work/PHPProject/shoplog:/var/www/html/data/log
+      - /Users/stanley-king/work/PHPProject/stdata:/var/www/html/data/stdata
+    container_name: "panda-reader"
+    command: ['python','reader.py']

+ 26 - 0
docker/compose/xyz-stat/docker-compose.yml

@@ -0,0 +1,26 @@
+version: "3.7"
+
+services:
+  readersrv:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../conf/etc/localtime:/etc/localtime:ro
+      - ../../../:/var/www/html
+      - /nfs/upload:/var/www/html/data/upload
+      - /mnt/shoplog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "panda-reader"
+    command: ['python','reader.py']
+
+  flasksrv:
+    image: pycpu:3.7.10
+    ports:
+      - "5000:5000"
+    volumes:
+      - ../../conf/etc/localtime:/etc/localtime:ro
+      - ../../../:/var/www/html
+      - /nfs/upload:/var/www/html/data/upload
+      - /mnt/shoplog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "panda-flask"
+    command: ['python','app.py']

+ 11 - 0
docker/conf/nginx/nginx-stanley-http.conf

@@ -61,6 +61,17 @@ http
 	        try_files $uri $uri/ /mshop/index.html;
         }
 
+        location /plot {
+            root $folder_name;
+            proxy_pass         http://host.docker.internal:5000;
+            proxy_redirect     off;
+
+            proxy_set_header   Host                 $host;
+            proxy_set_header   X-Real-IP            $remote_addr;
+            proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
+            proxy_set_header   X-Forwarded-Proto    $scheme;
+        }
+
         location ~ /mobile/[/\w]+\.php$ {
             root           $folder_name;
             fastcgi_pass   host.docker.internal:9100;

+ 11 - 0
docker/conf/nginx/nginx-xyz-https.conf

@@ -73,6 +73,17 @@ http
             try_files $uri $uri/ /mshop/index.html;
         }
 
+        location /plot {
+            root $folder_name;
+            proxy_pass         http://172.26.105.127:5000;
+              proxy_redirect     off;
+
+            proxy_set_header   Host                 $host;
+            proxy_set_header   X-Real-IP            $remote_addr;
+            proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
+            proxy_set_header   X-Forwarded-Proto    $scheme;
+        }
+
         location /merchant {
             root $folder_name;
             autoindex on;

+ 11 - 6
helper/mtopcard/mtopcard.php

@@ -183,8 +183,9 @@ function simple_card_type($cardno)
     }
 }
 
-function card_type($cardno)
+function card_type($cardno,&$regin_no)
 {
+    $regin_no = -1;
     if(preg_match( '/^1[0-9]{18}$/',$cardno,$matches)) {
         return SinopecCard;
     }
@@ -193,14 +194,14 @@ function card_type($cardno)
     }
     elseif(preg_match('/^1\d{10}$/',$cardno,$matches))
     {
-        $region_no = -1;
-        $checker = function ($phone) use(&$region_no)
+        $checker = function ($phone,&$region)
         {
             if (empty($phone)) return false;  //手机号不能为空
             $url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel={$phone}";
             $resp = http_request($url);  //获取API返回 的数据
-            $resp = mb_convert_encoding($resp, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5'); //解决中文乱码
+            if(empty($resp)) return false;
 
+            $resp = mb_convert_encoding($resp, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5'); //解决中文乱码
             $datas = explode('=', $resp);
             if(count($datas) == 2)
             {
@@ -209,7 +210,7 @@ function card_type($cardno)
                     $res = array_combine($m[1], $m[2]);
 
                     $province = formatProvince($res['province']);
-                    $region_no = array_search($province,ProvinceList);
+                    $region = array_search($province,ProvinceList);
                     return $res;
                 }
             }
@@ -217,9 +218,10 @@ function card_type($cardno)
             return false;
         };
 
-        $ret = $checker($cardno);
+        $ret = $checker($cardno,$region);
         if (empty($ret))
         {
+            $regin_no = -1;
             Log::record("淘宝接口没法使用了,用传统办法识别卡类型",Log::DEBUG);
             if (preg_match('/^134[0-8]\d{7}$|^(?:13[5-9]|147|15[0-27-9]|17[28]|18[2-478]|19[578])\d{8}$/', $cardno, $matches)) {
                 return ChinaMobileCard;
@@ -232,12 +234,15 @@ function card_type($cardno)
             }
         }
         elseif($ret['catName'] == '中国联通') {
+            $regin_no = $region;
             return ChinaUnicomCard;
         }
         elseif($ret['catName'] == '中国电信') {
+            $regin_no = $region;
             return ChinaTelecomCard;
         }
         elseif($ret['catName'] == '中国移动') {
+            $regin_no = $region;
             return ChinaMobileCard;
         }
         else {

+ 26 - 0
helper/refill/IRefill.php

@@ -2,6 +2,7 @@
 
 
 namespace refill;
+use Composer\Package\Package;
 use mtopcard;
 
 abstract class IRefill
@@ -14,12 +15,14 @@ abstract class IRefill
     protected $mPeriod;
     protected $mOpened;
     protected $mSort;
+    protected $mSupportRegins;
 
     public function __construct($cfgs)
     {
         $this->mName = $cfgs['name'];
         $this->mStoreID = $cfgs['store_id'];
         $this->mRefillType = $cfgs['refill_type'];
+        $this->mSupportRegins = [];
 
         $card_types = function ($stypes)
         {
@@ -51,11 +54,34 @@ abstract class IRefill
 
         $this->mOpened = true;
         $this->mSort = 65536;
+        $this->mSupportRegins = [];
     }
 
     abstract public function add($card_no,$card_type,$amount,$params);
     abstract public function query($refill_info);
 
+    //分省相关
+    public function setRegins($regins) {
+        $this->mSupportRegins = $regins;
+    }
+
+    public function isRegin(): bool {
+        return !empty($this->mSupportRegins);
+    }
+
+    public function match_regin($card_type,$regin_no): bool
+    {
+        if(empty($this->mSupportRegins) || empty($this->mSupportRegins[$card_type])) {
+            return true;
+        }
+        elseif(in_array(-1,$this->mSupportRegins[$card_type])) {
+            return true;
+        }
+        else {
+            return in_array($regin_no,$this->mSupportRegins[$card_type]);
+        }
+    }
+    //
     public function name() {
         return $this->mName;
     }

+ 26 - 7
helper/refill/ProviderManager.php

@@ -137,8 +137,10 @@ class ProviderManager
             foreach ($channels as $item)
             {
                 $name = $item['name'];
+                $regins = $item['regins'];
                 if(array_key_exists($name,$this->mProviders)) {
                     $this->mProviders[$name]->setOpened($item['opened']);
+                    $this->mProviders[$name]->setRegins($regins);
                 }
             }
         }
@@ -154,22 +156,39 @@ class ProviderManager
         $items = $refill_provider->getProviderList(['provider_id' => ['gt' , 0]]);
 
         $result = [];
-        foreach ($items as $item) {
+        foreach ($items as $item)
+        {
             $name = $item['name'];
+
+            $regins = [];
+            $tmp = unserialize($item['provinces']);
+            if(!empty($tmp))
+            {
+                foreach ($tmp as $card_type => $sregions)
+                {
+                    $regins = explode(',',$sregions);
+                    if(!empty($regins)) {
+                        $regins[$card_type] = $regins;
+                    }
+                }
+            }
+
+
             $val = ['name' => $name,
-                    'type' => intval($item['type']),
-                    'opened' => intval($item['opened']) == 1,
-                    'sort' => intval($item['sort'])];
+                'type' => intval($item['type']),
+                'opened' => intval($item['opened']) == 1,
+                'sort' => intval($item['sort']),
+                'regins' => $regins
+            ];
             $result[$name] = $val;
         }
 
         return $result;
     }
 
-    public function find_providers(int $spec, int $card_type,int $quality): array
+    public function find_providers(int $spec, int $card_type,int $quality,$regin_no): array
     {
         $qnames = $this->mSpecTypes[$quality] ?? [];
-//        $this->debug();
 
         $key = "{$card_type}-{$spec}";
         Log::record("quality = {$quality} , key = {$key}",Log::DEBUG);
@@ -182,7 +201,7 @@ class ProviderManager
             {
                 Log::record("name = {$name}",Log::DEBUG);
                 $provider = $this->mProviders[$name];
-                if($provider->opened()) {
+                if($provider->opened() && $provider->match_regin($card_type,$regin_no)) {
                     $providers[] = $provider;
                 }
             }

+ 9 - 7
helper/refill/RefillBase.php

@@ -127,7 +127,6 @@ class RefillBase
 //                        }
 
                         util::push_add($params);
-
                         return true;
                     }
                 }
@@ -168,6 +167,7 @@ class RefillBase
             'amount' => $refill_info['refill_amount'],
             'card_no' => $refill_info['card_no'],
             'card_type' => $refill_info['card_type'],
+            'regin_no' => $refill_info['regin_no'],
             'org_quality' => $org_quality,
             'mch_order' =>  $refill_info['mch_order'],
             'notify_url' => $refill_info['notify_url'],
@@ -185,7 +185,7 @@ class RefillBase
                         $mch_order, $idcard, $card_name, $notify_url,$quality,$org_quality,
                         $order_time = 0, $commit_times = 0,$errmsg='')
     {
-        $card_type = mtopcard\card_type($card_no);
+        $card_type = mtopcard\card_type($card_no,$regin_no);
         $minfo = new member_info($buyer_id);
 
         $calc = new ZeroMerchantPrice($mchid, $amount, $card_type,$quality);
@@ -239,12 +239,12 @@ class RefillBase
     //     其它情况,则需要判断订单ID
     public function add($mchid, $buyer_id, $amount, $card_no,
                         $mch_order, $idcard, $card_name, $notify_url, $quality, $org_quality,
-                        $order_time, $commit_times, $last_orderid = 0, $card_type = 0)
+                        $order_time, $commit_times, $last_orderid = 0, $card_type = 0,$regin_no = 0)
     {
         if($card_type == 0) {
-            $card_type = mtopcard\card_type($card_no);
+            $card_type = mtopcard\card_type($card_no,$regin_no);
         }
-        [$providers,$overload] = $this->mPolicy->find_providers($amount,$card_type,$quality);
+        [$providers, $overload] = $this->mPolicy->find_providers($amount, $card_type, $quality, $regin_no);
 
         if (empty($providers))
         {
@@ -323,7 +323,8 @@ class RefillBase
                     'notify_url' => $notify_url, 'channel_name' => $channel_name,
                     'mch_amount' => $mch_amount, 'channel_amount' => $price,
                     'order_time' => $order_time, 'commit_times' => $commit_times,
-                    'card_type' => $card_type, 'card_no' => $card_no,'quality' => $quality,'org_quality'=> $org_quality];
+                    'card_type' => $card_type, 'regin_no' => $regin_no,
+                    'card_no' => $card_no, 'quality' => $quality, 'org_quality' => $org_quality];
                 $mod_refill->add_refill($orderext);
 
                 if(!$this->pay_completed($order_sn)) {
@@ -441,7 +442,8 @@ class RefillBase
             $refill_order->edit($order_id, ['mch_notify_state' => 1, 'mch_notify_times' => ['exp', 'mch_notify_times+1']]);
             return [true, ""];
         }
-        else {
+        else
+        {
             $refill_order->edit($order_id, ['mch_notify_times' => ['exp', 'mch_notify_times+1']]);
             $times = $refill_info['mch_notify_times'] + 1;
 

+ 1 - 1
helper/refill/api/lingzh/amingjd/RefillPhone.php

@@ -105,7 +105,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 0;

+ 1 - 1
helper/refill/api/lingzh/wailing/RefillPhone.php

@@ -108,7 +108,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 0;

+ 1 - 1
helper/refill/api/lingzh/wuchen/RefillPhone.php

@@ -138,7 +138,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 1;

+ 1 - 1
helper/refill/api/test/baidu/RefillPhone.php

@@ -73,7 +73,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 2;

+ 1 - 1
helper/refill/api/xyz/afand/RefillPhone.php

@@ -109,7 +109,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 2;

+ 1 - 1
helper/refill/api/xyz/jiec/RefillPhone.php

@@ -100,7 +100,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 2;

+ 1 - 1
helper/refill/api/xyz/weit/RefillPhone.php

@@ -107,7 +107,7 @@ class RefillPhone extends refill\IRefillPhone
 
     private function phone_type($phone)
     {
-        $card_type = mtopcard\card_type($phone);
+        $card_type = mtopcard\card_type($phone,$regin_no);
 
         if ($card_type == mtopcard\ChinaMobileCard) {
             return 2;

+ 4 - 2
helper/refill/policy/chctl.php

@@ -72,14 +72,16 @@ class chctl
 
         //去掉已经关闭通道
         $usable_items = [];
-        foreach ($ctl_items as $item) {
+        foreach ($ctl_items as $item)
+        {
             if($item->opened()) {
                 $usable_items[] = $item;
             }
         }
 
         //不过载的排在前面
-        $ascending = function ($l, $r) {
+        $ascending = function ($l, $r)
+        {
             $lproity = $l->priority();
             $rproity = $r->priority();
 

+ 3 - 3
helper/refill/policy/lingzh/policy.php

@@ -31,9 +31,9 @@ class policy extends ProviderManager implements IPolicy
         $this->mPrices->load();
     }
 
-    public function find_providers(int $spec, int $card_type,int $quality): array
+    public function find_providers(int $spec, int $card_type,int $quality,$regin_no): array
     {
-        $providers = parent::find_providers($spec,$card_type,$quality);
+        $providers = parent::find_providers($spec,$card_type,$quality,$regin_no);
 
         if(empty($providers)) {
             return [$providers,false];
@@ -91,7 +91,7 @@ class policy extends ProviderManager implements IPolicy
                 continue;
             }
 
-            [$providers,$overload] = $this->find_providers($spec,$card_type,$quality);
+            [$providers,$overload] = $this->find_providers($spec,$card_type,$quality,-1);
             if (!empty($providers))
             {
                 if (!$overload) {

+ 3 - 3
helper/refill/policy/xyz/policy.php

@@ -40,9 +40,9 @@ class policy extends ProviderManager implements IPolicy
     }
 
 
-    public function find_providers(int $spec, int $card_type,int $quality): array
+    public function find_providers(int $spec, int $card_type,int $quality,$regin_no): array
     {
-        $providers = parent::find_providers($spec,$card_type,$quality);
+        $providers = parent::find_providers($spec,$card_type,$quality,$regin_no);
 
         if(empty($providers)) {
             return [$providers,false];
@@ -100,7 +100,7 @@ class policy extends ProviderManager implements IPolicy
                 continue;
             }
 
-            [$providers,$overload] = $this->find_providers($spec,$card_type,$quality);
+            [$providers,$overload] = $this->find_providers($spec,$card_type,$quality,-1);
             if (!empty($providers))
             {
                 if (!$overload) {

+ 1 - 43
helper/refill/util.php

@@ -88,7 +88,7 @@ class util
             $ret = $mod_topcard->get_card($card_no);
             if (empty($ret)) {
                 if ($card_type === 0) {
-                    $card_type = mtopcard\card_type($card_no);
+                    $card_type = mtopcard\card_type($card_no,$regin_no);
                 }
                 $bind_phone = util::make_mobile();
                 $mod_topcard->add($card_no, $card_type, time(), $bind_phone);
@@ -296,18 +296,14 @@ class util
 
         $name = 'channel_monitor_commit';
         $sec = time();
-        $min = $sec - $sec % 60;
 
         if ($fsuccess) {
             $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
-            $key_min = "succm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
         } else {
             $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
-            $key_min = "failm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
         }
 
         $ins->hIncrBy($name, $key_sec, 1);
-        $ins->hIncrBy($name, $key_min, 1);
     }
 
     public static function hget_commit_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
@@ -325,23 +321,6 @@ class util
         return intval($value);
     }
 
-    public static function hget_commit_min($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
-    {
-        $ins = Cache::getInstance('cacheredis');
-
-        $name = 'channel_monitor_commit';
-        $min = $time_stamp - $time_stamp % 60;
-
-        if ($fsuccess) {
-            $key_sec = "succm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
-        } else {
-            $key_sec = "failm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
-        }
-        $value = $ins->hget($name, '', $key_sec);
-
-        return intval($value);
-    }
-
     //统计回调通知数据
     public static function incr_notify($chname, $card_type, $spec, $quality, $fsuccess = true)
     {
@@ -349,18 +328,14 @@ class util
 
         $name = 'channel_monitor_notify';
         $sec = time();
-        $min = $sec - $sec % 60;
 
         if ($fsuccess) {
             $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
-            $key_min = "succm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
         } else {
             $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
-            $key_min = "failm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
         }
 
         $ins->hIncrBy($name, $key_sec, 1);
-        $ins->hIncrBy($name, $key_min, 1);
     }
 
     public static function hget_notify_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
@@ -378,23 +353,6 @@ class util
         return intval($value);
     }
 
-    public static function hget_notify_min($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
-    {
-        $ins = Cache::getInstance('cacheredis');
-
-        $name = 'channel_monitor_notify';
-        $min = $time_stamp - $time_stamp % 60;
-
-        if ($fsuccess) {
-            $key_sec = "succm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
-        } else {
-            $key_sec = "failm-{$chname}-{$quality}-{$card_type}-{$spec}-{$min}";
-        }
-        $value = $ins->hget($name, '', $key_sec);
-
-        return intval($value);
-    }
-
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     public static function incr_amount_lock($mchid, $card_type, $spec)
     {

+ 1 - 1
mobile/control/merchant_refill.php

@@ -49,7 +49,7 @@ class merchant_refillControl extends mbMerchantControl
         }
 
         $card_no = $params['cardno'];
-        $card_type = mtopcard\card_type($card_no);
+        $card_type = mtopcard\card_type($card_no,$regin_no);
 
         if($card_type == mtopcard\UnknownCard) {
             return [false,'卡类型无法识别'];

+ 294 - 0
plot/DataCenter.py

@@ -0,0 +1,294 @@
+from threading import Thread
+import os
+import time as stime
+from Singleton import Singleton
+import redis
+import h5py
+from os import path
+import re
+from datetime import timedelta
+import numpy as np
+from matplotlib.figure import Figure
+from matplotlib import ticker
+from io import BytesIO
+import logging
+
+
+class DataCenter(object):
+    pos_map = {
+        'commit-succ': 0, 'commit-fail': 1, 'notify-succ': 2, 'notify-fail': 3, 'user_succ': 4
+    }
+
+    def __init__(self):
+        self._mquit = False
+        self._file_name = '/var/www/html/data/stdata/data.hdf5'
+
+    def stop(self):
+        self._mquit = True
+        pass
+
+    def prepare_data(self):
+        while True:
+            try:
+                # pool = redis.ConnectionPool(host='121.89.223.81', port=57649, db=0)
+                pool = redis.ConnectionPool(host='172.26.105.125', port=6379, db=0)
+                r = redis.Redis(connection_pool=pool)
+
+                if path.exists(self._file_name):
+                    hfive = h5py.File(self._file_name, 'a')
+                else:
+                    hfive = h5py.File(self._file_name, 'w')
+
+                self.read_redis(hfive, r, 'nc_channel_monitor_commit', 'commit')
+                self.read_redis(hfive, r, 'nc_channel_monitor_notify', 'notify')
+                hfive.close()
+
+                self.del_redis(r, 'nc_channel_monitor_commit')
+                self.del_redis(r, 'nc_channel_monitor_notify')
+            except Exception as ex:
+                print(ex)
+            finally:
+                for i in range(60):
+                    if self._mquit == True:
+                        break
+                    else:
+                        stime.sleep(1)
+
+    def del_redis(self, redis, name):
+        latest_time = int(stime.time()) - 300
+        for item in redis.hscan_iter(name):
+            key = str(item[0], encoding="utf-8")
+            items = re.split(r'-', key)
+
+            fdel = True
+            if len(items) == 6:
+                (stype, chname, quality, card_type, amount, time) = items
+                time = int(time)
+                if latest_time <= time:
+                    fdel = False
+
+            if fdel:
+                redis.hdel(name, key)
+        pass
+
+    def read_redis(self, hfive, redis, name, prefix):
+        i = 0
+        for item in redis.hscan_iter(name):
+            key = str(item[0], encoding="utf-8")
+            val = str(item[1], encoding="utf-8")
+            print(f'{prefix}:{i}')
+            i += 1
+            self.parase(hfive, key, val, prefix)
+
+    def parase(self, hfive, text, val, prefix):
+        items = re.split(r'-', text)
+        if len(items) != 6:
+            return False
+
+        (stype, chname, quality, card_type, amount, time) = items
+        if stype == 'succ':
+            pos = self.pos_map[f'{prefix}-succ']
+        elif stype == 'fail':
+            pos = self.pos_map[f'{prefix}-fail']
+        else:
+            return False
+
+        time = int(time)
+        today = self.day_stamp(time)
+        path = f'/{today}/{chname}/{quality}/{card_type}/{amount}'
+        if path not in hfive:
+            hfive[path] = np.zeros((5, 86400))
+
+        diff = time - today
+        if diff < 0:
+            print(diff)
+        hfive[path][pos, diff] = val
+        print(path, pos, diff, val, hfive[path][pos, diff])
+        pass
+
+    def day_stamp(self, stamp):
+        stamp = int(stamp)
+        x = stime.gmtime(stamp + 8 * 3600)
+        diff = timedelta(hours=x.tm_hour, minutes=x.tm_min, seconds=x.tm_sec)
+        today = stamp - diff.total_seconds()
+        return int(today)
+
+    def _days(self, root):
+        result = []
+        try:
+            for name, sub in root.items():
+                if isinstance(sub, h5py.Group):
+                    result.append(name)
+        except Exception as ex:
+            print(ex)
+        finally:
+            return result
+
+    def days(self):
+        try:
+            hfive = h5py.File(self._file_name, 'r')
+            root = hfive.require_group('/')
+            days = self._days(root)
+            hfive.close()
+            return days
+        except Exception as ex:
+            print(ex)
+            return []
+
+    def paths(self,time_stamp):
+        try:
+            day_stamp = self.day_stamp(time_stamp)
+            hfive = h5py.File(self._file_name, 'r')
+            group = hfive.require_group(f'/{day_stamp}')
+            paths = self.dir(group)
+            hfive.close()
+            return paths
+        except Exception as ex:
+            print(ex)
+            return []
+
+    def dir(self, group):
+        result = []
+        for name, sub in group.items():
+            if isinstance(sub, h5py.Group):
+                result.extend(self.dir(sub))
+            else:
+                result.append(sub.name)
+        return result
+
+    def draw_plot(self, start_time, interval=300, **kwargs):
+        logger = logging.getLogger('app')
+        hfive = h5py.File(self._file_name, 'r')
+        try:
+            filer_text, paths = self.datasets(hfive, start_time, **kwargs)
+            day_stamp = self.day_stamp(start_time)
+            start_pos = start_time - day_stamp
+
+            cur_day = self.day_stamp(stime.time())
+            if day_stamp == cur_day:
+                end_pos = int(stime.time()) - day_stamp
+            else:
+                end_pos = -1
+
+            fig = Figure(figsize=(16, 9))
+            ax = fig.subplots()
+
+            predata = np.zeros((5, 86400))
+            x = np.arange(0, 86400, interval)
+            for path, data in self.read_data(hfive, paths):
+                data = np.array(data)
+                predata = predata + data
+                self._draw_plot(ax, x, day_stamp, start_pos,end_pos, data, interval, path)
+                logger.info("path=%s", path)
+
+            self._draw_plot(ax, x, day_stamp, start_pos,end_pos, predata, interval, filer_text)
+
+            ax.legend()
+            ax.grid()
+            ax.set_title('success ratio')
+            ax.set(xlabel='time', ylabel='ratio')
+            fig.autofmt_xdate()
+
+            buf = BytesIO()
+            fig.savefig(buf, format="png")
+            return buf
+        except Exception as ex:
+            print(ex)
+        finally:
+            hfive.close()
+
+    def read_data(self, hfive, paths):
+        for path in paths:
+            yield path, hfive[path]
+
+
+
+    def datasets(self, hfive, start_time, **kwargs):
+        logger = logging.getLogger('app')
+
+        day_stamp = self.day_stamp(start_time)
+        sday = f'{day_stamp}'
+        root = hfive.require_group('/')
+        days = self._days(root)
+        if sday not in days:
+            return False
+
+        group = hfive.require_group(sday)
+        dsets = self.dir(group)
+
+        chname = quality = card_type = amount = None
+        for key, val in kwargs.items():
+            if val is None:
+                continue
+
+            if key == 'chname':
+                chname = val
+            elif key == 'quality':
+                quality = f'{val}'
+            elif key == 'card_type':
+                card_type = f'{val}'
+            elif key == 'amount':
+                amount = f'{val}'
+            else:
+                continue
+        return self._filter(dsets, chname=chname, quality=quality, card_type=card_type, amount=amount)
+
+    def _filter(self, dsets, chname=None, quality=None, card_type=None, amount=None):
+        filer_text = ''
+        if chname is not None:
+            filer_text = chname
+        if quality is not None:
+            filer_text = filer_text + f"-qua:{quality}"
+        if card_type is not None:
+            filer_text = filer_text + f"-type:{card_type}"
+        if amount is not None:
+            filer_text = filer_text + f"-amount:{amount}"
+
+        paths = []
+        for text in dsets:
+            items = re.split(r'/', text)
+            if len(items) != 6:
+                return False
+            (_, _sday, _chname, _quality, _card_type, _amount) = items
+            if (chname is not None) and (_chname != chname):
+                continue
+            if (quality is not None) and (_quality != quality):
+                continue
+            if (card_type is not None) and (_card_type != card_type):
+                continue
+            if (amount is not None) and (_amount != amount):
+                continue
+            paths.append(text)
+
+        return filer_text, paths
+
+    def _draw_plot(self, ax, x, day_stamp, start_pos,end_pos, data, interval=300, path=''):
+        import matplotlib.dates as mdate
+        # 'commit-succ': 0, 'commit-fail': 1, 'notify-succ': 2, 'notify-fail': 3, 'user_succ': 4
+
+        all = data[2] + data[3]
+        all = all.reshape((-1, interval))
+        all = np.sum(all, axis=1)
+
+        ySucc = data[2]
+        ySucc = ySucc.reshape((-1, interval))
+        ySucc = np.sum(ySucc, axis=1)
+        ySucc = ySucc / (all + 0.00000001)
+
+        if end_pos == -1:
+            pos = np.where(x >= start_pos)
+            x = x[pos]
+            ySucc = ySucc[pos]
+        else:
+            pos = np.where(start_pos <= x)
+            x = x[pos]
+            ySucc = ySucc[pos]
+            pos = np.where(x < end_pos)
+            x = x[pos]
+            ySucc = ySucc[pos]
+
+        xs = np.array([stime.strftime('%H:%M', stime.localtime(d + day_stamp)) for d in x])
+        ax.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=0))
+        ax.plot(xs, ySucc, ls='--', marker='o', label=path)
+
+dataCenter = DataCenter()

+ 9 - 0
plot/Singleton.py

@@ -0,0 +1,9 @@
+def Singleton(cls):
+    _instance = {}
+
+    def _singleton(*args, **kargs):
+        if cls not in _instance:
+            _instance[cls] = cls(*args, **kargs)
+        return _instance[cls]
+
+    return _singleton

+ 96 - 0
plot/app.py

@@ -0,0 +1,96 @@
+import os
+
+from gevent import monkey
+from gevent.pywsgi import WSGIServer
+from gevent import signal as geventsig
+import gevent
+from flask import Flask
+import base64
+from io import BytesIO
+from matplotlib.figure import Figure
+import json
+from DataCenter import dataCenter
+# from plog import initLog
+from flask import request, jsonify
+import logging
+from logging.handlers import RotatingFileHandler
+
+import time
+import signal as sig
+
+app = Flask(__name__)
+app.debug = True
+
+curname = __name__
+
+
+@app.route('/plot/index')
+def index():
+    time_stamp = request.args.get('time_stamp')
+    interval = request.args.get('interval')
+    chname = request.args.get('chname')
+    quality = request.args.get('quality')
+    card_type = request.args.get('card_type')
+    amount = request.args.get('amount')
+
+    app.logger.info('time_stamp=%s interval= %s chname=%s quality=%s card_type=%s amount=%s',
+                    time_stamp, interval, chname, quality, card_type, amount)
+
+    if time_stamp is None:
+        time_stamp = time.time()
+    else:
+        time_stamp = int(time_stamp)
+
+    if interval is None:
+        interval = 300
+    else:
+        interval = int(interval)
+
+    # buf = dataCenter.draw_plot(1618243200, chname=chname)
+    # , quality=quality, card_type=card_type, interval=interval,
+    #                        amount=amount)1618502478
+    buf = dataCenter.draw_plot(time_stamp, interval=interval, chname=chname, quality=quality, card_type=card_type,
+                               amount=amount)
+    data = base64.b64encode(buf.getbuffer()).decode("ascii")
+    return f"<img src='data:image/png;base64,{data}'/>"
+
+
+@app.route('/plot/days')
+def days():
+    datas = dataCenter.days()
+    return jsonify(datas)
+
+
+@app.route('/plot/paths')
+def paths():
+    time_stamp = request.args.get('time_stamp')
+    time_stamp = int(time_stamp)
+    paths = dataCenter.paths(time_stamp)
+    return jsonify(paths)
+
+
+if __name__ == "__main__":
+    handler = logging.FileHandler(filename='/var/www/html/data/log/plot.log')
+    handler.setLevel(logging.DEBUG)
+    logging_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+                                       datefmt='%Y-%m-%d %H:%M:%S')
+    handler.setFormatter(logging_format)
+    app.logger.addHandler(handler)
+
+    logger = logging.getLogger('app')
+    logger.info('app')
+
+    monkey.patch_all()
+    http_server = WSGIServer(('0.0.0.0', 5000), app)
+
+
+    def shutdown():
+        print('Shutting down ...')
+        http_server.stop()
+        exit(sig.SIGTERM)
+
+
+    geventsig.signal(sig.SIGTERM, lambda: http_server.stop())
+    geventsig.signal(sig.SIGINT, lambda: http_server.stop())
+
+    http_server.serve_forever()

+ 11 - 0
plot/plog.py

@@ -0,0 +1,11 @@
+import logging
+
+
+def initLog():
+    logging.basicConfig(filename='/var/www/html/data/log/plot.log', level=logging.INFO,
+                        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
+
+
+if __name__ == "__main__":
+    logger = initLog()
+    logging.info('start')

+ 11 - 0
plot/pywsgi.py

@@ -0,0 +1,11 @@
+import os
+
+from gevent import monkey
+from gevent.pywsgi import WSGIServer
+
+from app import app
+
+monkey.patch_all()
+
+http_server = WSGIServer(('0.0.0.0', int(os.environ['PORT_APP'])), app)
+http_server.serve_forever()

+ 6 - 0
plot/reader.py

@@ -0,0 +1,6 @@
+from DataCenter import dataCenter
+import signal as sig
+
+if __name__ == '__main__':
+    sig.signal(sig.SIGINT, lambda: dataCenter.stop())
+    dataCenter.prepare_data()

+ 107 - 0
plot/thdf5.py

@@ -0,0 +1,107 @@
+import unittest
+import redis
+import h5py
+import time
+from datetime import datetime
+from datetime import timedelta
+import re
+import threading
+import numpy as np
+from DataCenter import dataCenter
+from matplotlib.figure import Figure
+from PIL import Image
+from io import BytesIO
+from PIL import Image
+import json
+
+
+class DataTest(unittest.TestCase):
+    def test_parase(self):
+        try:
+            dataCenter.parase('succ-lingzh-1-4-50-1618184676', '1')
+        except Exception as ex:
+            print(ex)
+
+    # docker-compose up pythoncli python -m unittest thdf5.DataTest.test_predata
+    def test_predata(self):
+        try:
+            dataCenter.prepare_data()
+        except Exception as ex:
+            print(ex)
+
+    def test_connect(self):
+        pool = redis.ConnectionPool(host='121.89.223.81', port=57649, db=0)
+        r = redis.Redis(connection_pool=pool)
+        for item in r.hscan_iter('nc_channel_monitor_commit'):
+            key = item[0]
+            val = item[1]
+            print(str(key, encoding="utf-8"), str(val, encoding="utf-8"))
+
+    def test_regex(self):
+        text = 'succm-lingzh-1-4-30-1618291260'
+        result = re.split(r'-', text)
+        pass
+
+    def day(self, time):
+        pass
+
+    def test_today(self):
+        stamp = 1617908681
+        stamp = int(stamp)
+        x = time.gmtime(stamp + 8 * 3600)
+        diff = timedelta(hours=x.tm_hour, minutes=x.tm_min, seconds=x.tm_sec)
+        today = stamp - diff.total_seconds()
+        y = stamp - today
+        pass
+
+    def test_days(self):
+        days = dataCenter.days()
+        result = json.dumps(days)
+        print(days)
+
+    def test_data(self):
+        buf = dataCenter.draw_plot(1619020800, chname='lingzh')
+        img = Image.open(buf)
+        img.show()
+
+    def dir(self, group):
+        result = []
+        for name, sub in group.items():
+            if isinstance(sub, h5py.Group):
+                result.extend(self.dir(sub))
+            else:
+                print(sub.name)
+                result.append(sub.name)
+
+        return result
+
+    def test_h5pyr(self):
+        try:
+            file_name = '/var/www/html/data/stdata/data.hdf5'
+            f = h5py.File(file_name, 'r')
+            root = f.require_group('/')
+            result = self.dir(group=root)
+            f.close()
+        except Exception as ex:
+            print(ex)
+
+    def test_fig(self):
+        buf = dataCenter.draw()
+        img = Image.open(buf)
+        img.show()
+
+    def test_numpy(self):
+        x = np.arange(0, 86400)
+        y = x.reshape((-1, 300))
+        y = np.sum(y, axis=1)
+
+        pos = np.where(x >= 25890)
+        x = x[pos]
+        pos = np.where(x < 85400)
+        x = x[pos]
+
+        print(x)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 1 - 1
racc/control/refill.php

@@ -75,7 +75,7 @@ class refillControl extends merchantControl
             return self::outerr(206,"平台不支持该卡充值.");
         }
 
-//        $card_type = mtopcard\card_type($card_no);
+//        $card_type = mtopcard\card_type($card_no,$regin_no);
 //        if($card_type === mtopcard\SinopecCard || $card_type === mtopcard\PetroChinaCard)
 //        {
 //            $allow = refill\RefillFactory::instance()->allow($this->mchid(),$card_type,$amount);

+ 4 - 2
rdispatcher/proxy.php

@@ -31,14 +31,16 @@ class proxy
 
         $org_quality = intval($params['org_quality']) ?? 0;
         $card_type   = intval($params['card_type']) ?? 0;
+        $regin_no   = intval($params['regin_no']) ?? 0;
 
         Log::record("proxy::add mch_order={$mch_order} card_no = {$card_no}",Log::DEBUG);
 
         $need_check = false;
         if($card_type == 0)
         {
-            $card_type = mtopcard\card_type($card_no);
+            $card_type = mtopcard\card_type($card_no,$regin_no);
             $params['card_type'] = $card_type;
+            $params['regin_no'] = $regin_no;
 
             global $config;
             if($config['phone_life_check'] == true && $card_type != mtopcard\PetroChinaCard && $card_type != mtopcard\SinopecCard) {
@@ -61,7 +63,7 @@ class proxy
 
         [$errcode, $errmsg, $order_id, $neterr] = refill\RefillFactory::instance()->add($mchid, $buyer_id, $amount, $card_no,
             $mch_order, $idcard, $card_name, $notify_url, $quality,$org_quality,
-            $order_time, $commit_times, $last_order_id,$card_type);
+            $order_time, $commit_times, $last_order_id,$card_type,$regin_no);
         $params['commit_times'] += 1;
         $commit_times += 1;
 

+ 29 - 0
test/TestAddData.php

@@ -14,8 +14,11 @@ require_once(BASE_HELPER_PATH . '/order_helper.php');
 require_once(BASE_HELPER_PATH . '/bonus_helper.php');
 require_once(BASE_HELPER_PATH . '/vrorder_helper.php');
 require_once(BASE_HELPER_PATH . '/PHPExcel/PHPExcel.php');
+require_once (BASE_CORE_PATH . '/framework/function/http.php');
 
 use PHPUnit\Framework\TestCase;
+use function mtopcard\formatProvince;
+use const mtopcard\ProvinceList;
 
 class TestAddData extends TestCase
 {
@@ -32,6 +35,32 @@ class TestAddData extends TestCase
         $mod_card->addCard(['card_no' => $car_no,'card_key' => $card_key,'card_type' => $card_type,'amount' => $amount]);
     }
 
+    public function testRegin()
+    {
+        $card_type = mtopcard\card_type('13911129867',$regin);
+    }
+
+    public function testCardtype()
+    {
+        $url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13911129867";
+        $resp = http_request($url);  //获取API返回 的数据
+        if(empty($resp)) return false;
+
+        $resp = mb_convert_encoding($resp, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5'); //解决中文乱码
+        $datas = explode('=', $resp);
+        if(count($datas) == 2)
+        {
+            $body = trim($datas[1]);
+            if(preg_match_all("/(\w+):'([^']+)/", $body, $m)) {
+                $res = array_combine($m[1], $m[2]);
+
+                $province = formatProvince($res['province']);
+                $region = array_search($province,ProvinceList);
+                return $res;
+            }
+        }
+    }
+
     public function testReadCSVFile()
     {
         $items = [

+ 0 - 2
test/TestRedis.php

@@ -200,8 +200,6 @@ class TestRedis extends TestCase
 
         $x = 'http://www.sina.com.cn';
         $y = urlencode($x);
-
-
     }
 
     public function testMillsec()

+ 8 - 0
test/TestTime.php

@@ -140,6 +140,14 @@ class TestTime extends TestCase
         }
     }
 
+    public function testZero()
+    {
+        $x = time();
+        $date = date('Y-m-d H:i:s',1618243200);
+        $day_start = strtotime("{$date}");
+
+    }
+
     public function testDate()
     {
         $date = date('Y-m-d',time());