Переглянути джерело

Merge branch 'raccount' into rchannel

xiaoyu 2 роки тому
батько
коміт
916ef95dd7
100 змінених файлів з 3088 додано та 3031 видалено
  1. 3 1
      admin/control/merchant.php
  2. 14 1
      admin/control/provider.php
  3. 3 1
      admin/control/refill_analysis.php
  4. 9 4
      admin/control/refill_order.php
  5. 8 5
      admin/templates/default/analysis.new_version.mch_order_send.php
  6. 8 5
      admin/templates/default/analysis.new_version.provider.php
  7. 366 0
      admin/templates/default/analysis.cov.provider_succs.php
  8. 8 5
      admin/templates/default/analysis.new_version.system.php
  9. 288 0
      admin/templates/default/analysis.network.php
  10. 8 5
      admin/templates/default/analysis.provider.php
  11. 289 152
      admin/templates/default/analysis.system.php
  12. 10 1
      admin/templates/default/merchant.ctl.php
  13. 7 4
      admin/templates/default/merchant.ratios.php
  14. 7 2
      admin/templates/default/provider.amount.php
  15. 19 6
      admin/templates/default/provider.recharge.php
  16. 8 2
      admin/templates/default/refill.order.index.php
  17. 122 30
      data/config/xyz/refill.ini.php
  18. 151 22
      data/config/yl/refill.ini.php
  19. 1 1
      data/logic/buy_virtual.logic.php
  20. 8 2
      data/model/predeposit.model.php
  21. 15 0
      docker/compose/homecuda/plot/docker-compose.yml
  22. 0 106
      docker/compose/homecuda/stat/docker-compose.yml
  23. 11 0
      docker/compose/homecuda/statcalc/docker-compose.yml
  24. 19 0
      docker/compose/workcuda/database/docker-compose.yml
  25. 0 106
      docker/compose/workcuda/stat/docker-compose.yml
  26. 2 2
      docker/compose/workcuda/statcalc/docker-compose.yml
  27. 1 1
      docker/compose/workcuda/statwriter/docker-compose.yml
  28. 20 1
      docker/compose/xiaoyu/admin/docker-compose.yml
  29. 9 0
      docker/compose/xiaoyu/conf/nginx/nginx.conf
  30. 11 0
      docker/compose/xiaoyu/conf/php/vapi-spwan-start
  31. 15 0
      docker/compose/xyz/plot/docker-compose.yml
  32. 0 106
      docker/compose/xyz/stat/docker-compose.yml
  33. 10 0
      docker/compose/xyz/statcalc/docker-compose.yml
  34. 0 95
      docker/compose/xyzt/tstat/docker-compose.yml
  35. 0 78
      docker/compose/yl/ylstat/docker-compose.yml
  36. 10 0
      docker/compose/yl/ylstatcalc/docker-compose.yml
  37. 67 48
      helper/refill/RefillBase.php
  38. 50 0
      helper/refill/api/xyz/dazhanggui_high/RefillCallBack.php
  39. 142 0
      helper/refill/api/xyz/dazhanggui_high/RefillPhone.php
  40. 15 0
      helper/refill/api/xyz/dazhanggui_high/api.txt
  41. 35 0
      helper/refill/api/xyz/dazhanggui_high/config.php
  42. BIN
      helper/refill/api/xyz/guochuang/20220826广东移动调价函.png
  43. BIN
      helper/refill/api/xyz/guochuang/20220827广东移动调价函.png
  44. BIN
      helper/refill/api/xyz/guochuang/20220829山西移动调价函.png
  45. BIN
      helper/refill/api/xyz/guochuang/20220830青海移动调价函.png
  46. BIN
      helper/refill/api/xyz/guochuang/20220906广东移动调价函.png
  47. 4 4
      helper/refill/api/xyz/guochuang/config.php
  48. 11 30
      helper/refill/api/xyz/ruixunda/RefillCallBack.php
  49. 62 62
      helper/refill/api/xyz/ruixunda/RefillPhone.php
  50. 38 32
      helper/refill/api/xyz/ruixunda/config.php
  51. BIN
      helper/refill/api/xyz/ruixunda/云九一商品编码.docx
  52. 37 0
      helper/refill/api/xyz/ruixunda/对接文档-yezi.txt
  53. 0 37
      helper/refill/api/xyz/ruixunda/开户信息.txt
  54. 4 3
      helper/refill/api/xyz/yelin_hf/RefillCallBack.php
  55. 3 2
      helper/refill/api/xyz/yelin_hf/RefillPhone.php
  56. 50 0
      helper/refill/api/yl/dazhanggui_high/RefillCallBack.php
  57. 142 0
      helper/refill/api/yl/dazhanggui_high/RefillPhone.php
  58. 15 0
      helper/refill/api/yl/dazhanggui_high/api.txt
  59. 35 0
      helper/refill/api/yl/dazhanggui_high/config.php
  60. 4 4
      helper/refill/api/yl/guochuang/config.php
  61. 11 30
      helper/refill/api/yl/ruixunda/RefillCallBack.php
  62. 62 62
      helper/refill/api/yl/ruixunda/RefillPhone.php
  63. 38 32
      helper/refill/api/yl/ruixunda/config.php
  64. BIN
      helper/refill/api/yl/ruixunda/云九一商品编码.docx
  65. 35 0
      helper/refill/api/yl/ruixunda/对接文档-yezi.txt
  66. 0 37
      helper/refill/api/yl/ruixunda/开户信息.txt
  67. 48 0
      helper/refill/api/yl/weixue/RefillCallBack.php
  68. 155 0
      helper/refill/api/yl/weixue/RefillPhone.php
  69. 44 0
      helper/refill/api/yl/weixue/config.php
  70. 29 0
      helper/refill/api/yl/weixue/对接文档-yezi.txt
  71. 76 0
      helper/refill/api/yl/yezi_hf/RefillCallBack.php
  72. 155 0
      helper/refill/api/yl/yezi_hf/RefillPhone.php
  73. 7 0
      helper/refill/api/yl/yezi_hf/api.txt
  74. 13 0
      helper/refill/api/yl/yezi_hf/config.php
  75. 141 0
      helper/refill/ops/pdlog_clear_refill.php
  76. 1 1
      helper/refill/policy/ctl_itemex.php
  77. 4 4
      helper/refill/policy/quaility.php
  78. 4 0
      mobile/callback/refill_dazhanggui_high.php
  79. 1 1
      mobile/callback/refill_ruixunda.php
  80. 4 0
      mobile/callback/refill_yezi_hf.php
  81. 0 439
      plot/DataCenter.py
  82. 0 76
      plot/Fetcher.py
  83. 0 681
      plot/MchDataCenter.py
  84. 0 9
      plot/Singleton.py
  85. 0 185
      plot/SpeedDataCenter.py
  86. 0 52
      plot/UserFetcher.py
  87. 67 110
      plot/app.py
  88. 0 25
      plot/chspeed.py
  89. 0 25
      plot/flask_test.py
  90. 0 31
      plot/mchreader.py
  91. 0 23
      plot/mcounts.py
  92. 0 23
      plot/mratio.py
  93. 0 23
      plot/mratios.py
  94. 19 0
      plot/mtimesratio.py
  95. 0 11
      plot/plog.py
  96. 0 128
      plot/plot_control.py
  97. 0 11
      plot/pywsgi.py
  98. 0 23
      plot/ratio.py
  99. 0 23
      plot/reader.py
  100. 0 0
      plot/refill/ChSpeedRatioCalc.py

+ 3 - 1
admin/control/merchant.php

@@ -1217,6 +1217,8 @@ class merchantControl extends SystemControl
                 $retry_times_cfg['profit_ratio'] = $profit_ratio;
                 $profit_formula = $_POST['profit_formula'] ?? '';
                 $retry_times_cfg['profit_formula'] = $profit_formula;
+                $only_high_prices = intval($_POST['only_high_prices']) ?? 0;
+                $retry_times_cfg['only_high_prices'] = $only_high_prices;
                 return serialize($retry_times_cfg);
             };
             $retry_times_cfg = $retry_times_data($qualitys);
@@ -1312,4 +1314,4 @@ class merchantControl extends SystemControl
         }
         return $transfer_cfg;
     }
-}
+}

+ 14 - 1
admin/control/provider.php

@@ -138,6 +138,18 @@ class providerControl extends SystemControl
                 showMessage('金额错误');
             }
 
+            if (!empty($_FILES['voucher']['name'])) {
+                $upload = new UploadFile();
+                $upload->set('default_dir', ATTACH_UPFILE);
+
+                $result = $upload->upfile('voucher');
+                if ($result) {
+                    $_POST['voucher_name'] = $upload->file_name;
+                } else {
+                    showMessage($upload->error);
+                }
+            }
+
             try {
                 $model_merchant = Model('merchant');
                 $trans = new trans_wapper($model_merchant, __METHOD__);
@@ -180,6 +192,7 @@ class providerControl extends SystemControl
         $input['operation'] = $params['operation'];
         $input['add_time'] = time();
         $input['bz'] = $params['bz'] ?? '';
+        $input['voucher_name'] = $params['voucher_name'] ?? '';
 
         return Model('provider_amount')->addAmount($input);
     }
@@ -734,4 +747,4 @@ class providerControl extends SystemControl
         }
         return $result;
     }
-}
+}

+ 3 - 1
admin/control/refill_analysis.php

@@ -24,6 +24,8 @@ class refill_analysisControl extends SystemControl
             $url = $this->ANALYSIS_URL . '/plot/mchdays';
         } elseif($type == 'provider') {
             $url = $this->ANALYSIS_URL . '/plot/days';
+        } else {
+            return [];
         }
 
         Log::record("analysis get timestamp url : {$url}", Log::DEBUG);
@@ -158,7 +160,7 @@ class refill_analysisControl extends SystemControl
     public function new_versionOp()
     {
         $type = $_GET['type'] ?? 'provider';
-        $page = "analysis.new_version.{$type}";
+        $page = "analysis.cov.{$type}";
         if($type == 'provider')
         {
             global $config;

+ 9 - 4
admin/control/refill_order.php

@@ -53,9 +53,6 @@ class refill_orderControl extends SystemControl
             if (!empty($input['mchid'])) {
                 $cond['refill_order.mchid'] = $input['mchid'];
             }
-            if (!empty($input['channel_name'])) {
-                $cond['refill_order.channel_name'] = $input['channel_name'];
-            }
             if (!empty($input['store_id'])) {
                 $cond['vr_order.store_id'] = $input['store_id'];
             }
@@ -73,6 +70,14 @@ class refill_orderControl extends SystemControl
                     $cond['official_sn'] = ['neq', ''];
                 }
             }
+            if(!empty($input['have_chname']))
+            {
+                if($input['have_chname'] == 1) {
+                    $cond['refill_order.channel_name'] = '';
+                } elseif ($input['have_chname'] == 2) {
+                    $cond['refill_order.channel_name'] = ['neq', ''];
+                }
+            }
 
             if (!empty($input['card_type'])) {
                 if (in_array($input['card_type'], ['1', '2', '4', '5', '6', '7'])) {
@@ -477,4 +482,4 @@ class refill_orderControl extends SystemControl
         }
         showMessage('操作成功');
     }
-}
+}

+ 8 - 5
admin/templates/default/analysis.new_version.mch_order_send.php

@@ -50,11 +50,14 @@
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>平台成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>平台累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
                 <li><a href="JavaScript:void(0);" class="current"><span>机构单量监控</span></a></li>
             </ul>
         </div>
@@ -336,4 +339,4 @@
 
         $('#ncsubmit').trigger('click');
     })
-</script>
+</script>

+ 8 - 5
admin/templates/default/analysis.new_version.provider.php

@@ -51,11 +51,14 @@
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>平台成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="JavaScript:void(0);" class="current"><span>通道累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>平台累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
             </ul>
         </div>
@@ -360,4 +363,4 @@
         $('.querySelect').trigger('change');
         $('#ncsubmit').trigger('click');
     })
-</script>
+</script>

+ 366 - 0
admin/templates/default/analysis.cov.provider_succs.php

@@ -0,0 +1,366 @@
+<style>
+    #checkChannel {
+        border-spacing: 0;
+        border-collapse: collapse;
+    }
+
+    #checkChannel td {
+        min-width: 110px;
+        height: 20px;
+        padding: 2px;
+        background: #F3FBFE;
+        border: 1px solid #fff;
+        display: block;
+        white-space: nowrap;
+        font-size: 10px;
+    }
+
+    #checkChannel tr {
+        height: 20px;
+    }
+
+    #checkChannel thead tr {
+        table-layout: fixed;
+        top: 0;
+        left: 0;
+    }
+
+    #checkChannel tbody {
+        height: calc(100vh - 150px);
+        display: block;
+        overflow-y: scroll;
+    }
+
+    .echartsContent {
+        display: flex;
+        height: calc(100vh - 150px);
+    }
+
+    #echart {
+        flex: 1;
+        margin-left: 5px;
+    }
+
+    #echart img {
+        width: 100%;
+    }
+</style>
+
+<div class="page">
+    <div class="fixed-bar">
+        <div class="item-title">
+            <h3>成功率监控列表</h3>
+            <ul class="tab-base">
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="JavaScript:void(0);" class="current"><span>通道按时段成功单量监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
+            </ul>
+        </div>
+    </div>
+    <div class="fixed-empty"></div>
+    <!-- <div style="margin-top: 10px;color: #e60d0d;">
+        请先选择时间
+    </div> -->
+    <form method="get" action="index.php" name="formSearch" id="formSearch" style="min-width: 1200px;">
+        <table class="tb-type1 noborder search tableFixed">
+            <tr>
+                <th><label for="query_start_time">统计时间</label></th>
+                <td>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_start_time']; ?>" id="startTime" name="query_start_time" autocomplete="off" style="width:120px" />
+                    <label for="query_start_time">~</label>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_end_time']; ?>" id="endTime" name="query_end_time" autocomplete="off" style="width:120px" />
+                </td>
+                <th><label>通道质量</label></th>
+                <td>
+                    <select name="quality" class="querySelect">
+                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="">全部</option>
+                        <option value="<?php echo refill\Quality::Normal; ?>">普充(无流水)
+                        </option>
+                        <option value="<?php echo refill\Quality::Quick; ?>">快充
+                        </option>
+                        <option value="<?php echo refill\Quality::CardKey; ?>">卡密
+                        </option>
+                        <option value="<?php echo refill\Quality::ThirdShop; ?>">三方
+                        </option>
+                        <option value="<?php echo refill\Quality::SlowTwentyFour; ?>">慢24(有流水)
+                        </option>
+                        <option value="<?php echo refill\Quality::SlowSix; ?>">慢6
+                        </option>
+                        <option value="<?php echo refill\Quality::SlowTwo; ?>">慢2
+                        </option>
+                        <option value="<?php echo refill\Quality::SlowFortyEight; ?>">慢48
+                        </option>
+                        <option value="<?php echo refill\Quality::SlowSeventyTwo; ?>">慢72
+                        </option>
+                        <option value="<?php echo refill\Quality::Fastest; ?>">速充
+                        </option>
+                    </select>
+                </td>
+                <th><label>卡类型</label></th>
+                <td>
+                    <div id="select_cardtypes"></div>
+                </td>
+                <th><label>面额</label></th>
+                <td>
+                    <select name="amount">
+                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="10" <?php if ($_GET['refill_amount'] == '10') { ?>selected<?php } ?>>10</option>
+                        <option value="20" <?php if ($_GET['refill_amount'] == '20') { ?>selected<?php } ?>>20</option>
+                        <option value="30" <?php if ($_GET['refill_amount'] == '30') { ?>selected<?php } ?>>30</option>
+                        <option value="50" <?php if ($_GET['refill_amount'] == '50') { ?>selected<?php } ?>>50</option>
+                        <option value="100" <?php if ($_GET['refill_amount'] == '100') { ?>selected<?php } ?>>100</option>
+                        <option value="200" <?php if ($_GET['refill_amount'] == '200') { ?>selected<?php } ?>>200</option>
+                        <option value="300" <?php if ($_GET['refill_amount'] == '300') { ?>selected<?php } ?>>300</option>
+                        <option value="500" <?php if ($_GET['refill_amount'] == '500') { ?>selected<?php } ?>>500</option>
+                        <option value="1000" <?php if ($_GET['refill_amount'] == '1000') { ?>selected<?php } ?>>1000</option>
+                        <option value="2000" <?php if ($_GET['refill_amount'] == '2000') { ?>selected<?php } ?>>2000</option>
+                    </select>
+                </td>
+                <th><label>窗口时长</label></th>
+                <td>
+                    <select name="filter_wave">
+                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
+                        <option value="0" selected>关闭</option>
+                    </select>
+                </td>
+                <td>
+                    <a href="javascript:void(0);" id="ncsubmit" class="btn-search" title="<?php echo $lang['nc_query']; ?>">&nbsp;
+                    </a>
+                </td>
+            </tr>
+        </table>
+
+        <div class="echartsContent">
+            <table id="checkChannel">
+                <thead>
+                    <tr>
+                        <td>
+                            <label>
+                                <input type="checkbox" id="checkAllChannel">
+                                编号(通道列表)
+                            </label>
+                        </td>
+                    </tr>
+                </thead>
+                <tbody id="checkChannelContent">
+
+                </tbody>
+            </table>
+            <div id="echart">
+
+            </div>
+        </div>
+
+
+
+    </form>
+    <div id="box">
+        <!-- <iframe
+            src="https://www.xyzshops.cn/plot/index?time_stamp=1621488600&interval=60" scrolling="no" id="Iframe" frameborder="0"></iframe> -->
+    </div>
+</div>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/laydate/laydate.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/jquery.ui.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/i18n/zh-CN.js" charset="utf-8"></script>
+<script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL; ?>/js/xm-select.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/layer.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/moment-with-locales.js"></script>
+<link rel="stylesheet" type="text/css" href="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/themes/ui-lightness/jquery.ui.css" />
+<script type="text/javascript">
+    $(function() {
+
+        var provider = <?php echo json_encode($output['providers']) ?>
+
+        let ratios = [];
+
+        let qualitys = [];
+
+        const defaultChannelType = <?php echo refill\Quality::Normal; ?>;
+
+        $.get(`index.php?act=refill_analysis&op=provider_data`, function(data) {
+            data = JSON.parse(data)
+            if (data.length > 0) {
+                qualitys = data;
+                formatChannelTable(data);
+            }
+        })
+
+        function formatChannelTable(tableData) {
+            $('#checkChannelContent').children().remove();
+            let data;
+            if (typeof tableData == 'object') {
+                data = tableData;
+            } else {
+                data = JSON.parse(tableData)
+            }
+
+            let tableHTML = '';
+            data.map(item => {
+                tableHTML += `
+                    <tr>
+                        <td><label><input type="checkbox" name="channelValue" ${item.checked?'checked="checked"':''}  value="${item.value}" />${item.name}${item.ratio?`<span style="color:red;">(${item.ratio})</span>`:''}</label></td>
+                    </tr>
+                `;
+            })
+            $('#checkChannelContent').append(tableHTML);
+        }
+
+        laydate.render({
+            elem: '#startTime',
+            type: 'datetime'
+        });
+        laydate.render({
+            elem: '#endTime',
+            type: 'datetime'
+        });
+
+
+        let select_cardtypes
+        $.get('index.php?act=refill_analysis&op=card_type_data', function(data) {
+            data = JSON.parse(data)
+            select_cardtypes = xmSelect.render({
+                el: '#select_cardtypes',
+                size: 'mini',
+                filterable: true,
+                style: {
+                    minHeight: '27px',
+                    lineHeight: '27px',
+                    marginLeft: '4px',
+                    width: '250px'
+                },
+                language: 'zn',
+                data: data
+            })
+        })
+
+        function select_set(selectArr) {
+            let selectStr = ''
+            for (let i = 0; i < selectArr.length; i++) {
+                selectStr += selectArr[i].value + ','
+            }
+            selectStr = selectStr.substr(0, selectStr.length - 1)
+            return selectStr
+        }
+
+        function updateQualityTable() {
+            const allQualityList = JSON.parse(JSON.stringify(qualitys));
+
+            allQualityList.map(item => {
+                item.checked = false;
+            })
+
+
+            function findItem(value) {
+                const item = allQualityList.filter(item => {
+                    return item.value == value;
+                })
+                if (item.length > 0) {
+                    return item[0].name
+                }
+                return false
+            }
+            const ratioList = ratios.map(item => {
+                return {
+                    name: findItem(item.split(':')[0]) || item.split(':')[0],
+                    value: item.split(':')[0],
+                    ratio: item.split(':')[1],
+                    checked: parseFloat(item.split(':')[1]) == 0 ? false : true
+                }
+            });
+
+
+            let mergeQualitys = [...ratioList, ...allQualityList];
+
+            const newArr = [];
+            const obj = {};
+
+            for (let i = 0; i < mergeQualitys.length; i++) {
+                if (!obj[mergeQualitys[i].value]) {
+                    newArr.push(mergeQualitys[i]);
+                    obj[mergeQualitys[i].value] = true;
+                }
+            }
+
+            formatChannelTable(newArr);
+        }
+
+        $('#ncsubmit').click(function() {
+            let query_start_time = $("input[name=query_start_time]").val()
+            let start_time = parseInt((new Date(query_start_time)).getTime() / 1000);
+            let query_end_time = $("input[name=query_end_time]").val()
+            let end_time = parseInt((new Date(query_end_time)).getTime() / 1000);
+
+            if (!start_time && !end_time) {
+                start_time = Date.parse(new Date()) / 1000 - 7200;
+                end_time = Date.parse(new Date()) / 1000;
+            }
+
+            let chnamesList = [];
+            $('input[name="channelValue"]').each(function() {
+                if ($(this).attr('checked')) {
+                    chnamesList.push($(this).attr('value'))
+                }
+            })
+
+            let chnames = chnamesList.join(',');
+
+
+            let card_types = select_cardtypes && select_set(select_cardtypes.getValue())
+            let spec = $("select[name=amount]").val()
+            let filter_wave = $("select[name=filter_wave]").val()
+            let src = window.location.origin + "/plot/ch_covsuccs?"
+            if (start_time) {
+                src += "&start_time=" + start_time;
+            }
+            if (end_time) {
+                if (end_time < start_time || !start_time) {
+                    layer.msg('日期有误,结束日期需大于开始日期');
+                    return
+                }
+                src += "&end_time=" + end_time;
+            }
+            if (chnames) {
+                src += "&chnames=" + chnames;
+            }
+            if (card_types) {
+                src += "&card_types=" + card_types;
+            }
+            if (spec) {
+                src += "&spec=" + spec;
+            }
+            if (filter_wave > 0) {
+                src += '&filter_wave=' + filter_wave;
+            }
+            $.get(src, function(data)
+            {
+                if (data.state == 'success') {
+                    $('#echart').html(`<img src='data:image/png;base64,${data.img}'/>`)
+                    ratios = data.ratios;
+                    updateQualityTable()
+                }
+            });
+        });
+
+        $('#checkAllChannel').click(function() {
+            if ($(this).get(0).checked) {
+                $('input[name="channelValue"]').attr('checked', 'checked')
+            } else {
+                $('input[name="channelValue"]').removeAttr('checked')
+            }
+        })
+
+        $('.querySelect').trigger('change');
+        $('#ncsubmit').trigger('click');
+    })
+</script>

+ 8 - 5
admin/templates/default/analysis.new_version.system.php

@@ -49,11 +49,14 @@
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>平台成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
-                <li><a href="JavaScript:void(0);" class="current"><span>平台累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="JavaScript:void(0);" class="current"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
             </ul>
         </div>
@@ -342,4 +345,4 @@
 
         $('#ncsubmit').trigger('click');
     })
-</script>
+</script>

+ 288 - 0
admin/templates/default/analysis.network.php

@@ -0,0 +1,288 @@
+<style>
+    #checkChannel {
+        border-spacing: 0;
+        border-collapse: collapse;
+    }
+
+    #checkChannel td {
+        min-width: 110px;
+        height: 20px;
+        padding: 2px;
+        background: #F3FBFE;
+        border: 1px solid #fff;
+        display: block;
+        white-space: nowrap;
+        font-size: 10px;
+    }
+
+    #checkChannel tr {
+        height: 20px;
+    }
+
+    #checkChannel thead tr {
+        table-layout: fixed;
+        top: 0;
+        left: 0;
+    }
+
+    #checkChannel tbody {
+        height: calc(100vh - 150px);
+        display: block;
+        overflow-y: scroll;
+    }
+
+    .echartsContent {
+        display: flex;
+        height: calc(100vh - 150px);
+    }
+
+    #echart {
+        flex: 1;
+        margin-left: 5px;
+    }
+
+    #echart img {
+        width: 100%;
+    }
+</style>
+
+<div class="page">
+    <div class="fixed-bar">
+        <div class="item-title">
+            <h3>成功率监控列表</h3>
+            <ul class="tab-base">
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
+                <li><a href="JavaScript:void(0);" class="current"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
+            </ul>
+        </div>
+    </div>
+    <div class="fixed-empty"></div>
+    <!-- <div style="margin-top: 10px;color: #e60d0d;">
+        请先选择时间
+    </div> -->
+    <form method="get" action="index.php" name="formSearch" id="formSearch" style="min-width: 1200px;">
+        <table class="tb-type1 noborder search tableFixed">
+            <tr>
+                <th><label for="query_start_time">统计时间</label></th>
+                <td>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_start_time']; ?>" id="startTime" name="query_start_time" autocomplete="off" style="width:120px" />
+                    <label for="query_start_time">~</label>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_end_time']; ?>" id="endTime" name="query_end_time" autocomplete="off" style="width:120px" />
+                </td>
+
+                <th><label>窗口时长</label></th>
+                <td>
+                    <select name="filter_wave">
+                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
+                        <option value="0" selected>关闭</option>
+                    </select>
+                </td>
+                <td>
+                    <a href="javascript:void(0);" id="ncsubmit" class="btn-search" title="<?php echo $lang['nc_query']; ?>">&nbsp;
+                    </a>
+                </td>
+            </tr>
+        </table>
+
+        <div class="echartsContent">
+            <table id="checkChannel">
+                <thead>
+                <tr>
+                    <td>
+                        <label>
+                            <input type="checkbox" id="checkAllChannel">
+                            编号(通道列表)
+                        </label>
+                    </td>
+                </tr>
+                </thead>
+                <tbody id="checkChannelContent">
+
+                </tbody>
+            </table>
+            <div id="echart">
+
+            </div>
+        </div>
+
+
+
+    </form>
+    <div id="box">
+        <!-- <iframe
+            src="https://www.xyzshops.cn/plot/index?time_stamp=1621488600&interval=60" scrolling="no" id="Iframe" frameborder="0"></iframe> -->
+    </div>
+</div>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/laydate/laydate.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/jquery.ui.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/i18n/zh-CN.js" charset="utf-8"></script>
+<script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL; ?>/js/xm-select.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/layer.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/moment-with-locales.js"></script>
+<link rel="stylesheet" type="text/css" href="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/themes/ui-lightness/jquery.ui.css" />
+<script type="text/javascript">
+    $(function() {
+        let ratios = [];
+
+        let qualitys = [];
+
+        $.get(`index.php?act=refill_analysis&op=provider_data`, function(data) {
+            data = JSON.parse(data)
+            if (data.length > 0) {
+                qualitys = data;
+                formatChannelTable(data);
+            }
+        })
+
+        function formatChannelTable(tableData) {
+            $('#checkChannelContent').children().remove();
+            let data;
+            if (typeof tableData == 'object') {
+                data = tableData;
+            } else {
+                data = JSON.parse(tableData)
+            }
+
+            let tableHTML = '';
+            data.map(item => {
+                tableHTML += `
+                    <tr>
+                        <td><label><input type="checkbox" name="channelValue" ${item.checked?'checked="checked"':''}  value="${item.value}" />${item.name}${item.ratio?`<span style="color:red;">(${item.ratio})</span>`:''}</label></td>
+                    </tr>
+                `;
+            })
+            $('#checkChannelContent').append(tableHTML);
+        }
+
+        laydate.render({
+            elem: '#startTime',
+            type: 'datetime'
+        });
+        laydate.render({
+            elem: '#endTime',
+            type: 'datetime'
+        });
+
+
+        function select_set(selectArr) {
+            let selectStr = ''
+            for (let i = 0; i < selectArr.length; i++) {
+                selectStr += selectArr[i].value + ','
+            }
+            selectStr = selectStr.substr(0, selectStr.length - 1)
+            return selectStr
+        }
+
+        function updateQualityTable() {
+            const allQualityList = JSON.parse(JSON.stringify(qualitys));
+
+            allQualityList.map(item => {
+                item.checked = false;
+            })
+
+
+            function findItem(value) {
+                const item = allQualityList.filter(item => {
+                    return item.value == value;
+                })
+                if (item.length > 0) {
+                    return item[0].name
+                }
+                return false
+            }
+            const ratioList = ratios.map(item => {
+                return {
+                    name: findItem(item.split(':')[0]) || item.split(':')[0],
+                    value: item.split(':')[0],
+                    ratio: item.split(':')[1],
+                    checked: parseFloat(item.split(':')[1]) == 0 ? false : true
+                }
+            });
+
+
+            let mergeQualitys = [...ratioList, ...allQualityList];
+
+            const newArr = [];
+            const obj = {};
+
+            for (let i = 0; i < mergeQualitys.length; i++) {
+                if (!obj[mergeQualitys[i].value]) {
+                    newArr.push(mergeQualitys[i]);
+                    obj[mergeQualitys[i].value] = true;
+                }
+            }
+
+            formatChannelTable(newArr);
+        }
+
+        $('#ncsubmit').click(function() {
+            let query_start_time = $("input[name=query_start_time]").val()
+            let start_time = parseInt((new Date(query_start_time)).getTime() / 1000);
+            let query_end_time = $("input[name=query_end_time]").val()
+            let end_time = parseInt((new Date(query_end_time)).getTime() / 1000);
+
+            if (!start_time && !end_time) {
+                start_time = Date.parse(new Date()) / 1000 - 7200;
+                end_time = Date.parse(new Date()) / 1000;
+            }
+
+            let chnamesList = [];
+            $('input[name="channelValue"]').each(function() {
+                if ($(this).attr('checked')) {
+                    chnamesList.push($(this).attr('value'))
+                }
+            })
+
+            let chnames = chnamesList.join(',');
+
+            let filter_wave = $("select[name=filter_wave]").val()
+            let src = window.location.origin + "/plot/net_check?"
+            if (start_time) {
+                src += "&start_time=" + start_time;
+            }
+            if (end_time) {
+                if (end_time < start_time || !start_time) {
+                    layer.msg('日期有误,结束日期需大于开始日期');
+                    return
+                }
+                src += "&end_time=" + end_time;
+            }
+            if (chnames) {
+                src += "&chnames=" + chnames;
+            }
+            if (filter_wave > 0) {
+                src += '&filter_wave=' + filter_wave;
+            }
+            $.get(src, function(data)
+            {
+                if (data.state == 'success') {
+                    $('#echart').html(`<img src='data:image/png;base64,${data.img}'/>`)
+                    ratios = data.ratios;
+                    updateQualityTable()
+                }
+            });
+        });
+
+        $('#checkAllChannel').click(function() {
+            if ($(this).get(0).checked) {
+                $('input[name="channelValue"]').attr('checked', 'checked')
+            } else {
+                $('input[name="channelValue"]').removeAttr('checked')
+            }
+        })
+
+        $('.querySelect').trigger('change');
+        $('#ncsubmit').trigger('click');
+    })
+</script>

+ 8 - 5
admin/templates/default/analysis.provider.php

@@ -51,11 +51,14 @@
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="JavaScript:void(0);" class="current" ><span>通道成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>平台成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="JavaScript:void(0);" class="current" ><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>平台累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
             </ul>
         </div>
@@ -360,4 +363,4 @@
         $('.querySelect').trigger('change');
         $('#ncsubmit').trigger('click');
     })
-</script>
+</script>

+ 289 - 152
admin/templates/default/analysis.system.php

@@ -1,211 +1,348 @@
+<style>
+    #checkChannel {
+        border-spacing: 0;
+        border-collapse: collapse;
+    }
+
+    #checkChannel td {
+        height: 20px;
+        padding: 2px;
+        background: #F3FBFE;
+        border: 1px solid #fff;
+        display: block;
+        white-space: nowrap;
+        font-size: 10px;
+    }
+
+    #checkChannel tr {
+        height: 20px;
+    }
+
+    #checkChannel thead tr {
+        table-layout: fixed;
+        top: 0;
+        left: 0;
+    }
+
+    #checkChannel tbody {
+        height: calc(100vh - 150px);
+        display: block;
+        overflow-y: scroll;
+    }
+
+    .echartsContent {
+        display: flex;
+        height: calc(100vh - 150px);
+    }
+
+    #echart {
+        flex: 1;
+        margin-left: 5px;
+    }
+
+    #echart img {
+        width: 100%;
+    }
+</style>
 <div class="page">
     <div class="fixed-bar">
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道成功率监控</span></a></li>
-                <li><a href="JavaScript:void(0);" class="current"><span>平台成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>平台累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
 
+                <li><a href="JavaScript:void(0);" class="current"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=merchant_ratios"><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
             </ul>
         </div>
     </div>
     <div class="fixed-empty"></div>
-    <div style="margin-top: 10px;color: #e60d0d;">
+    <!-- <div style="margin-top: 10px;color: #e60d0d;">
         请先选择时间
-    </div>
+    </div> -->
     <form method="get" action="index.php" name="formSearch" id="formSearch" style="min-width: 1200px;">
         <table class="tb-type1 noborder search tableFixed">
             <tr>
-                <th><label>起始日期</label></th>
+                <th><label for="query_start_time">统计时间</label></th>
                 <td>
-                    <select name="time_stamp" id="timeSelect">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <?php foreach ($output['days'] as $day => $txt) {?>
-                            <option value="<?php echo $day; ?>"><?php echo $txt; ?></option>
-                        <?php }?>
-                    </select>
-                </td>
-                <th><label>起始时间</label></th>
-                <td>
-                    <select name="time_hour">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <?php for ($i = 0; $i <= 23; $i++) {?>
-                            <option value="<?php echo $i; ?>"><?php echo sprintf("%02d",$i); ?>点</option>
-                        <?php }?>
-                    </select>
-                </td>
-                <th><label>起始分钟</label></th>
-                <td>
-                    <select name="minute">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <?php for ($i = 0; $i <= 59; $i++) {?>
-                            <option value="<?php echo $i; ?>"><?php echo sprintf("%02d",$i); ?>分</option>
-                        <?php }?>
-                    </select>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_start_time']; ?>" id="startTime" name="query_start_time" autocomplete="off" style="width:120px" />
+                    <label for="query_start_time">~</label>
+                    <input class="txt date" type="text" value="<?php echo $_GET['query_end_time']; ?>" id="endTime" name="query_end_time" autocomplete="off" style="width:120px" />
                 </td>
-                <th><label>间隔</label></th>
+                <!-- <th><label>机构选择</label></th>
                 <td>
-                    <select name="interval">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="3600">一小时</option>
-                        <option value="1800">半小时</option>
-                        <option value="900" >15分钟</option>
-                        <option value="600" >10分钟</option>
-                        <option value="300">5分钟</option>
-                        <option value="60" selected>1分钟</option>
-                    </select>
-                </td>
-                <th><label>客户</label></th>
-                <td>
-                    <select name="chname">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                    </select>
-                </td>
-                <th><label>质量</label></th>
+                    <div id="select_merchants"></div>
+                </td> -->
+                <th><label>卡类型</label></th>
                 <td>
-                    <select name="quality">
-                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                    </select>
+                    <div id="select_cardtypes"></div>
                 </td>
-                <th><label>卡类型</label></th>
+                <th><label>面额</label></th>
                 <td>
-                    <select name="card_type">
+                    <select name="amount">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="10" <?php if ($_GET['refill_amount'] == '10') { ?>selected<?php } ?>>10</option>
+                        <option value="20" <?php if ($_GET['refill_amount'] == '20') { ?>selected<?php } ?>>20</option>
+                        <option value="30" <?php if ($_GET['refill_amount'] == '30') { ?>selected<?php } ?>>30</option>
+                        <option value="50" <?php if ($_GET['refill_amount'] == '50') { ?>selected<?php } ?>>50</option>
+                        <option value="100" <?php if ($_GET['refill_amount'] == '100') { ?>selected<?php } ?>>100</option>
+                        <option value="200" <?php if ($_GET['refill_amount'] == '200') { ?>selected<?php } ?>>200</option>
+                        <option value="300" <?php if ($_GET['refill_amount'] == '300') { ?>selected<?php } ?>>300</option>
+                        <option value="500" <?php if ($_GET['refill_amount'] == '500') { ?>selected<?php } ?>>500</option>
+                        <option value="1000" <?php if ($_GET['refill_amount'] == '1000') { ?>selected<?php } ?>>1000</option>
+                        <option value="2000" <?php if ($_GET['refill_amount'] == '2000') { ?>selected<?php } ?>>2000</option>
                     </select>
                 </td>
-                <th><label>面额</label></th>
+                <th><label>窗口时长</label></th>
                 <td>
-                    <select name="amount">
+                    <select name="filter_wave">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
+                        <option value="0" selected>关闭</option>
                     </select>
                 </td>
                 <td>
-                    <a href="javascript:void(0);" id="ncsubmit" class="btn-search "
-                       title="<?php echo $lang['nc_query']; ?>">&nbsp;
+                    <a href="javascript:void(0);" id="ncsubmit" class="btn-search" title="<?php echo $lang['nc_query']; ?>">&nbsp;
                     </a>
                 </td>
             </tr>
         </table>
     </form>
+
+    <div class="echartsContent">
+        <table id="checkChannel">
+            <thead>
+            <tr>
+                <td>
+                    <label>
+                        <input type="checkbox" id="checkAllChannel">
+                        编号(机构列表)
+                    </label>
+                </td>
+            </tr>
+            </thead>
+            <tbody id="checkChannelContent">
+
+            </tbody>
+        </table>
+        <div id="echart">
+
+        </div>
+    </div>
+
     <div id="box">
         <!-- <iframe
-            src="" scrolling="no" id="Iframe" frameborder="0"></iframe> -->
+            src="https://www.xyzshops.cn/plot/index?time_stamp=1621488600&interval=60" scrolling="no" id="Iframe" frameborder="0"></iframe> -->
     </div>
 </div>
 <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/laydate/laydate.js"></script>
 <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/jquery.ui.js"></script>
-<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/i18n/zh-CN.js"
-        charset="utf-8"></script>
-<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL;?>/refill/layer.js"></script>
-<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL;?>/refill/moment-with-locales.js"></script>
-<link rel="stylesheet" type="text/css"
-      href="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/themes/ui-lightness/jquery.ui.css"/>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/i18n/zh-CN.js" charset="utf-8"></script>
+<script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL; ?>/js/xm-select.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/layer.js"></script>
+<script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/refill/moment-with-locales.js"></script>
+<link rel="stylesheet" type="text/css" href="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/themes/ui-lightness/jquery.ui.css" />
 <script type="text/javascript">
-    $(function () {
-        // 前15分钟
-        let time = Date.parse(new Date());
-        time = time - 900000;
-        let hour = moment(time).format("H")
-        let minute = moment(time).format("m")
-        time = time / 1000;
-
-        let interval = $("select[name=interval]").val()
-        let s = window.location.origin + "/plot/mchplot?time_stamp=" + time + "&interval=" + interval
-        let timestamp = new Date(new Date().toLocaleDateString()).getTime() / 1000;
-
-        $("select[name=time_stamp]").val(timestamp)
-        $("select[name=time_hour]").val(hour)
-        $("select[name=minute]").val(minute)
-        TimeGetWhere(timestamp)
-        $.get( s, function (data){
-            if (!data) {
-                return
-            }
-            // $('iframe').attr('src',s)
-            $('#box').html(data)
+    $(function() {
+
+        let ratios = [];
+
+        let qualitys = [];
+
+
+        laydate.render({
+            elem: '#startTime',
+            type: 'datetime'
+        });
+        laydate.render({
+            elem: '#endTime',
+            type: 'datetime'
         });
 
-        function TimeGetWhere(time){
-            $.get("index.php?act=refill_analysis&op=analysis_time_get_where&type=system&timestamp="+time, function (data){
-                if (!data) {
-                    return
-                }
-                data = JSON.parse(data)
-                $("select[name=chname]").find('.chnameOption').remove();
-                $("select[name=quality]").find('.qualityOption').remove();
-                $("select[name=card_type]").find('.ctOption').remove();
-                $("select[name=amount]").find('.amountOption').remove();
-                // 通道
-                for (const key in data.chname) {
-                    $("select[name=chname]").append("<option class='chnameOption' value='"+key+"'>"+data.chname[key]+"</option>")
-                }
-                // 质量
-                for (const key in data.quality) {
-                    // console.log('质量', key, data.quality[key]);
-                    $("select[name=quality]").append("<option class='qualityOption' value='"+key+"'>"+data.quality[key]+"</option>")
-                }
-                // 卡类型
-                for (const key in data.card_type) {
-                    // console.log('类型', key, data.card_type[key]);
-                    $("select[name=card_type]").append("<option class='ctOption' value='"+key+"'>"+data.card_type[key]+"</option>")
+
+
+        function formatChannelTable(tableData) {
+            $('#checkChannelContent').children().remove();
+            let data;
+            if (typeof tableData == 'object') {
+                data = tableData;
+            } else {
+                data = JSON.parse(tableData)
+            }
+            let tableHTML = '';
+            data.map(item => {
+                tableHTML += `
+                    <tr>
+                        <td><label><input type="checkbox" name="channelValue" ${item.checked?'checked="checked"':''}  value="${item.value}" />${item.name}${item.ratio?`<span style="color:red;">(${item.ratio})</span>`:''}</label></td>
+                    </tr>
+                `;
+            })
+            $('#checkChannelContent').append(tableHTML);
+        }
+
+        function updateQualityTable() {
+            const allQualityList = JSON.parse(JSON.stringify(qualitys));
+
+            allQualityList.map(item => {
+                item.checked = false;
+            })
+
+
+            function findItem(value) {
+                const item = allQualityList.filter(item => {
+                    return item.value == value;
+                })
+                if (item.length > 0) {
+                    return item[0].name
                 }
-                // 面额
-                for (const key in data.amount) {
-                    // console.log('面额', data.amount[key]);
-                    $("select[name=amount]").append("<option class='amountOption' value='"+data.amount[key]+"'>"+data.amount[key]+"</option>")
+                return false
+            }
+            const ratioList = ratios.map(item => {
+                return {
+                    name: findItem(item.split(':')[0]) || item.split(':')[0],
+                    value: item.split(':')[0],
+                    ratio: item.split(':')[1],
+                    checked: parseFloat(item.split(':')[1]) == 0 ? false : true
                 }
-                // console.log('data1', data);
             });
+
+
+            let mergeQualitys = [...ratioList, ...allQualityList];
+
+            const newArr = [];
+            const obj = {};
+
+            for (let i = 0; i < mergeQualitys.length; i++) {
+                if (!obj[mergeQualitys[i].value]) {
+                    newArr.push(mergeQualitys[i]);
+                    obj[mergeQualitys[i].value] = true;
+                }
+            }
+
+            formatChannelTable(newArr);
+        }
+
+        // let select_merchants
+        $.get('index.php?act=refill_analysis&op=merchant_data', function(data) {
+            data = JSON.parse(data)
+            qualitys = data;
+            formatChannelTable(data)
+            // select_merchants = xmSelect.render({
+            //     el: '#select_merchants',
+            //     size: 'mini',
+            //     filterable: true,
+            //     style: {
+            //         minHeight: '27px',
+            //         lineHeight: '27px',
+            //         marginLeft: '4px',
+            //         width: '250px'
+            //     },
+            //     language: 'zn',
+            //     data: data
+            // })
+        })
+
+        let select_cardtypes
+        $.get('index.php?act=refill_analysis&op=card_type_data', function(data) {
+            data = JSON.parse(data)
+            select_cardtypes = xmSelect.render({
+                el: '#select_cardtypes',
+                size: 'mini',
+                filterable: true,
+                style: {
+                    minHeight: '27px',
+                    lineHeight: '27px',
+                    marginLeft: '4px',
+                    width: '250px'
+                },
+                language: 'zn',
+                data: data
+            })
+        })
+
+        function select_set(selectArr) {
+            let selectStr = ''
+            for (let i = 0; i < selectArr.length; i++) {
+                selectStr += selectArr[i].value + ','
+            }
+            selectStr = selectStr.substr(0, selectStr.length - 1)
+            return selectStr
         }
 
-        $('#timeSelect').change(function () {
-            let val = $(this).val()
-            // console.log('val', val);
-            TimeGetWhere(val);
+        $('#checkAllChannel').click(function() {
+            if ($(this).get(0).checked) {
+                $('input[name="channelValue"]').attr('checked', 'checked')
+            } else {
+                $('input[name="channelValue"]').removeAttr('checked')
+            }
         })
-        $('#ncsubmit').click(function () {
-            let time_stamp = $("select[name=time_stamp]").val()
-            let time_hour = $("select[name=time_hour]").val()
-            let minute = $("select[name=minute]").val()
-            let time = Number(time_stamp) + Number(time_hour)*3600 + Number(minute)*60
-            // console.log('time',time_stamp,time_hour,minute, time);
-            let interval = $("select[name=interval]").val()
-            let chname = $("select[name=chname]").val()
-            let quality = $("select[name=quality]").val()
-            let card_type = $("select[name=card_type]").val()
-            let amount = $("select[name=amount]").val()
-            if (!time_stamp) {
-                layer.msg('请选择时间');
-                return
+
+        $('#ncsubmit').click(function() {
+            let query_start_time = $("input[name=query_start_time]").val()
+            let start_time = parseInt((new Date(query_start_time)).getTime() / 1000);
+            let query_end_time = $("input[name=query_end_time]").val()
+            let end_time = parseInt((new Date(query_end_time)).getTime() / 1000);
+
+            if (!start_time && !end_time) {
+                start_time = Date.parse(new Date()) / 1000 - 7200;
+                end_time = Date.parse(new Date()) / 1000;
             }
-            let src = window.location.origin + "/plot/mchplot?time_stamp=" + time + "&interval=" + interval + "&mchid=" + chname + "&quality=" + quality + "&card_type=" + card_type + "&amount=" + amount
-            if (!interval) {
-                src = src.replace("&interval=", "")
+
+
+            // let mchids = select_set(select_merchants.getValue())
+            let mchidList = [];
+            $('input[name="channelValue"]').each(function() {
+                if ($(this).attr('checked')) {
+                    mchidList.push($(this).attr('value'))
+                }
+            })
+
+            let mchids = mchidList.join(',');
+
+
+            let card_types = select_cardtypes && select_set(select_cardtypes.getValue())
+            let spec = $("select[name=amount]").val()
+            let filter_wave = $("select[name=filter_wave]").val()
+            let src = window.location.origin + "/plot/mch_covratio?"
+            if (start_time) {
+                src += "&start_time=" + start_time;
             }
-            if (!chname) {
-                src = src.replace("&mchid=", "")
+            if (end_time) {
+                if (end_time < start_time || !start_time) {
+                    layer.msg('日期有误,结束日期需大于开始日期');
+                    return
+                }
+                src += "&end_time=" + end_time;
             }
-            if (!quality) {
-                src = src.replace("&quality=", "")
+            if (mchids) {
+                src += "&mchids=" + mchids;
             }
-            if (!card_type) {
-                src = src.replace("&card_type=", "")
+            if (card_types) {
+                src += "&card_types=" + card_types;
             }
-            if (!amount) {
-                src = src.replace("&amount=", "")
+            if (spec) {
+                src += "&spec=" + spec;
             }
-
-            $.get(src, function (data){
-                if (!data) {
-                    return
+            if (filter_wave > 0) {
+                src += '&filter_wave=' + filter_wave;
+            }
+            $.get(src, function(data) {
+                if (data.state == 'success') {
+                    $('#echart').html(`<img src='data:image/png;base64,${data.img}'/>`)
+                    ratios = data.ratios;
+                    updateQualityTable()
                 }
-                // $('iframe').attr('src',src)
-                $('#box').html(data)
             });
         });
+
+        $('#ncsubmit').trigger('click');
     })
-</script> 
+</script>

+ 10 - 1
admin/templates/default/merchant.ctl.php

@@ -179,6 +179,15 @@
                 </tr>
 
                 <tr class="noborder">
+                    <td colspan="2" class="required">
+                        <label style="margin-left: 45px;display: inline-block; width: 110px">允许只有高价通道:</label>
+                        <label>
+                            <input type="checkbox" name="only_high_prices" value="1" <?php if($output['retry_times']['only_high_prices'] === 1) { echo 'checked'; }?>>
+                        </label>
+                    </td>
+                </tr>
+
+                <tr class="noborder">
                     <td>
                         <hr>
                     </td>
@@ -550,4 +559,4 @@
             })
         })
     });
-</script>
+</script>

+ 7 - 4
admin/templates/default/merchant.ratios.php

@@ -47,11 +47,14 @@
         <div class="item-title">
             <h3>成功率监控列表</h3>
             <ul class="tab-base">
-                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>平台成功率监控</span></a></li>
-                <li><a href="JavaScript:void(0);" class="current" ><span>机构成功率统计</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=provider"><span>通道按时段成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider_succs"><span>通道按时段成功单量监控</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=provider"><span>通道累计成功率监控</span></a></li>
-                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>平台累计成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=index&type=network"><span>通道网络监控</span></a></li>
+
+                <li><a href="?index.php&act=refill_analysis&op=index&type=system"><span>机构成功率监控</span></a></li>
+                <li><a href="?index.php&act=refill_analysis&op=new_version&type=system"><span>机构累计成功率监控</span></a></li>
+                <li><a href="JavaScript:void(0);" class="current" ><span>机构成功率统计</span></a></li>
                 <li><a href="?index.php&act=refill_analysis&op=new_version&type=mch_order_send"><span>机构单量监控</span></a></li>
             </ul>
         </div>

+ 7 - 2
admin/templates/default/provider.amount.php

@@ -11,8 +11,8 @@
     .layui-form-select .layui-input {
         height:26px;
     }
-    input::placeholder{ 
-        color:#333; 
+    input::placeholder{
+        color:#333;
     }
     .layui-input {
         width: 160px!important;
@@ -123,6 +123,11 @@
                             <a href="index.php?act=provider&op=provider_amount_edit&amount_id=<?php echo $v['id'] ?>">编辑</a>
                             |
                             <a href="#" class="copy" data-name="<?php echo $v['name']; ?> (<?php echo $v['store_name'];?>)" data-amount="<?php echo $v['amount']; ?>">拷贝</a>
+                            <?php if(!empty($v['voucher_name'])) {?>
+                                |
+                                <a target="_blank"
+                                   href="<?php echo UPLOAD_SITE_URL . '/' . ATTACH_UPFILE . DS . $v['voucher_name']; ?>">预览</a>
+                            <?php }?>
                         </td>
                     </tr>
                 <?php } ?>

+ 19 - 6
admin/templates/default/provider.recharge.php

@@ -44,6 +44,19 @@
                 <td class="vatop tips"></td>
             </tr>
             <tr>
+                <td colspan="2"><label>充值申请凭证:</label></td>
+            </tr>
+            <tr class="noborder">
+                <td class="vatop rowform">
+                <span class="type-file-box">
+                    <input type='text' name='textfield' id='textfield1' class='type-file-text'/>
+                    <input type='button' name='button' id='button1' value='' class='type-file-button'/>
+                    <input name="voucher" type="file" class="type-file-file" id="voucher" size="30" hidefocus="true">
+                </span>
+                </td>
+                <td class="vatop tips"></td>
+            </tr>
+            <tr>
                 <td colspan="2" class="required"><label>备注信息:</label></td>
             </tr>
             <tr class="noborder">
@@ -138,7 +151,7 @@
           }
           return data_json;
         }
-    
+
         yi = yi_f(number_data);
         number_data = yi.data2;
         wan = wan_f(number_data);
@@ -147,7 +160,7 @@
         qian = qian_f(number_data);
         number_data = qian.data2;
 
-      
+
         let result = yi.data1 + wan.data1 + qian.data1  + number_data;
         let resultvalue = result.substr(0, 1)
 
@@ -160,12 +173,12 @@
         $("#money").text('')
         }else {
         $("#money").text(result)
-        }       
-    
+        }
+
     }
   $('#pointsnum').change(function () {
     let val =($(this).val())
      $('#money').text(cnMoneyFormat(val))
-  })         
+  })
     });
-</script>
+</script>

+ 8 - 2
admin/templates/default/refill.order.index.php

@@ -284,6 +284,12 @@
                             <option value="1000" <?php if ($_GET['refill_amount'] == '1000') { ?>selected<?php } ?>>1000</option>
                             <option value="2000" <?php if ($_GET['refill_amount'] == '2000') { ?>selected<?php } ?>>2000</option>
                         </select>
+                        <label>有无上游</label>
+                        <select name="have_chname">
+                            <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                            <option value="1" <?php if ($_GET['have_chname'] == '1') { ?>selected<?php } ?>>无上游通道</option>
+                            <option value="2" <?php if ($_GET['have_chname'] == '2') { ?>selected<?php } ?>>有上游通道</option>
+                        </select>
                     </td>
                     <th><label>通道质量</label></th>
                     <td>
@@ -530,7 +536,7 @@
                         <td class="align-left" class="ch_trade_no"><?php echo $order['ch_trade_no']; ?></td>
                         <td class="align-right"><?php echo $order['commit_times']; ?></td>
                         <td class="align-center"><?php echo $order['org_quality_text']; ?></td>
-                        <!--                    <td class="align-center">--><?php //echo $order['mch_amount']; 
+                        <!--                    <td class="align-center">--><?php //echo $order['mch_amount'];
                                                                             ?>
                         <!--</td>-->
                         <td class="align-center" id="Manual">
@@ -1082,4 +1088,4 @@
     function hCopyMchOrder(e) {
         copy_some(14)
     }
-</script>
+</script>

+ 122 - 30
data/config/xyz/refill.ini.php

@@ -526,21 +526,21 @@ $xc_phone = ['name' => 'xc', 'store_id' => 34, 'qualitys' => '4',
 
 $xunyin_phone = ['name' => 'xunyin', 'store_id' => 35,'qualitys' => '2',
     'amount' => [
-//        10 => [
+        10 => [
 //            ['goods_id' => 6438, 'price' => 10.01, 'quality' => 2, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 6438, 'price' => 10.01, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 6438, 'price' => 10.2, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 6438, 'price' => 10.01, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ],
-//        20 => [
+        ],
+        20 => [
 //            ['goods_id' => 6439, 'price' => 20.02, 'quality' => 2, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 6439, 'price' => 20.02, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 6439, 'price' => 20.2, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 6439, 'price' => 20.02, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ],
-//        30 => [
+        ],
+        30 => [
 //            ['goods_id' => 6440, 'price' => 30.03, 'quality' => 2, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 6440, 'price' => 30.03, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 6440, 'price' => 30.24, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 6440, 'price' => 29.03, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ],
+        ],
         50 => [
             ['goods_id' => 6441, 'price' => 50.05, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 6441, 'price' => 50.05, 'quality' => 2, 'card_type' => 'chinaunicom'],
@@ -3936,16 +3936,16 @@ $ruixunda_phone = ['name' => 'ruixunda', 'store_id' => 169, 'qualitys' => '1',
             ['goods_id' => 7444, 'price' => 187.8, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7444, 'price' => 189, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
-        300 => [
-            ['goods_id' => 7445, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7445, 'price' => 281.7, 'quality' => 1, 'card_type' => 'chinaunicom'],
-            ['goods_id' => 7445, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-        ],
-        500 => [
-            ['goods_id' => 7446, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7446, 'price' => 469.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
-            ['goods_id' => 7446, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-        ],
+//        300 => [
+//            ['goods_id' => 7445, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7445, 'price' => 281.7, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7445, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 7446, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7446, 'price' => 469.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7446, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -5901,36 +5901,36 @@ $bodian_phone = ['name' => 'bodian', 'store_id' => 226, 'qualitys' => '2',
 //            ['goods_id' => 7879, 'price' => 19.96, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7879, 'price' => 19.96, 'quality' => 2, 'card_type' => 'chinatelecom']
 //        ],
-//        30 => [
-//            ['goods_id' => 7880, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinamobile'],
+        30 => [
+            ['goods_id' => 7880, 'price' => 30.09, 'quality' => 2, 'card_type' => 'chinamobile'],
 //            ['goods_id' => 7880, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7880, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ],
+        ],
         50 => [
-//            ['goods_id' => 7881, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7881, 'price' => 50.15, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7881, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7881, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         100 => [
-//            ['goods_id' => 7882, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7882, 'price' => 100.3, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7882, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7882, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         200 => [
-//            ['goods_id' => 7883, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7883, 'price' => 200.6, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7883, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7883, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         300 => [
-//            ['goods_id' => 7884, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7884, 'price' => 300.9, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7884, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7884, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
-//        500 => [
-//            ['goods_id' => 7885, 'price' => 499, 'quality' => 2, 'card_type' => 'chinamobile'],
+        500 => [
+            ['goods_id' => 7885, 'price' => 501.5, 'quality' => 2, 'card_type' => 'chinamobile'],
 //            ['goods_id' => 7885, 'price' => 499, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7885, 'price' => 499, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ]
+        ]
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -6582,6 +6582,96 @@ $weixue_phone = ['name' => 'weixue', 'store_id' => 243, 'qualitys' => '1',
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
+$yelin_hf_phone = ['name' => 'yelin_hf', 'store_id' => 244, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8015, 'price' => 9.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8015, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8015, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8016, 'price' => 19.2, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8016, 'price' => 19, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8016, 'price' => 19, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        30 => [
+            ['goods_id' => 8017, 'price' => 28.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8017, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8017, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        50 => [
+            ['goods_id' => 8018, 'price' => 48, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8018, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8018, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8019, 'price' => 96, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8019, 'price' => 95, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8019, 'price' => 95, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8020, 'price' => 192, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8020, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8020, 'price' => 190, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 8021, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8021, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8021, 'price' => 285, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 8022, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8022, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8022, 'price' => 475, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
+$dazhanggui_high_phone = ['name' => 'dazhanggui_high', 'store_id' => 245, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8023, 'price' => 9.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8023, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8023, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8024, 'price' => 19.2, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8024, 'price' => 19, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8024, 'price' => 19, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        30 => [
+//            ['goods_id' => 8025, 'price' => 28.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8025, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8025, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        50 => [
+            ['goods_id' => 8026, 'price' => 48.75, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8026, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8026, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8027, 'price' => 97.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8027, 'price' => 95, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8027, 'price' => 95, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8028, 'price' => 195, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8028, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8028, 'price' => 190, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 8029, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8029, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8029, 'price' => 285, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 8030, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8030, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8030, 'price' => 475, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
 $phone_providers = [
 //    ['name' => 'beixt', 'cfg' => $beixt_phone],
 //    ['name' => 'bxtwt', 'cfg' => $bxtwt_phone],
@@ -6782,6 +6872,8 @@ $phone_providers = [
     ['name' => 'guitong_yi', 'cfg' => $guitong_yi_phone],
     ['name' => 'dazhanggui', 'cfg' => $dazhanggui_phone],
     ['name' => 'weixue', 'cfg' => $weixue_phone],
+    ['name' => 'yelin_hf', 'cfg' => $yelin_hf_phone],
+    ['name' => 'dazhanggui_high', 'cfg' => $dazhanggui_high_phone],
 
 ];
 $config['phone_providers'] = $phone_providers;
@@ -6870,4 +6962,4 @@ $third_providers = [
 $config['third_providers'] = $third_providers;
 
 $config['auto_find_channels'] = true;
-$config['cancel_retry_time'] = [10120 => ["9:00",'10:00','11:00']];
+$config['cancel_retry_time'] = [10120 => ["9:00",'10:00','11:00']];

+ 151 - 22
data/config/yl/refill.ini.php

@@ -3946,16 +3946,16 @@ $ruixunda_phone = ['name' => 'ruixunda', 'store_id' => 169, 'qualitys' => '1',
             ['goods_id' => 7444, 'price' => 187.8, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7444, 'price' => 189, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
-        300 => [
-            ['goods_id' => 7445, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7445, 'price' => 281.7, 'quality' => 1, 'card_type' => 'chinaunicom'],
-            ['goods_id' => 7445, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-        ],
-        500 => [
-            ['goods_id' => 7446, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7446, 'price' => 469.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
-            ['goods_id' => 7446, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-        ],
+//        300 => [
+//            ['goods_id' => 7445, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7445, 'price' => 281.7, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7445, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 7446, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7446, 'price' => 469.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7446, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -5735,36 +5735,36 @@ $bodian_phone = ['name' => 'bodian', 'store_id' => 219, 'qualitys' => '2',
 //            ['goods_id' => 7835, 'price' => 19.96, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7835, 'price' => 19.96, 'quality' => 2, 'card_type' => 'chinatelecom']
 //        ],
-//        30 => [
-//            ['goods_id' => 7836, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinamobile'],
+        30 => [
+            ['goods_id' => 7836, 'price' => 30.09, 'quality' => 2, 'card_type' => 'chinamobile'],
 //            ['goods_id' => 7836, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7836, 'price' => 29.94, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ],
+        ],
         50 => [
-//            ['goods_id' => 7837, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7837, 'price' => 50.15, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7837, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7837, 'price' => 49.9, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         100 => [
-//            ['goods_id' => 7838, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7838, 'price' => 100.3, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7838, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7838, 'price' => 99.8, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         200 => [
-//            ['goods_id' => 7839, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7839, 'price' => 200.6, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7839, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7839, 'price' => 199.6, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
         300 => [
-//            ['goods_id' => 7840, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7840, 'price' => 300.9, 'quality' => 2, 'card_type' => 'chinamobile'],
             ['goods_id' => 7840, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7840, 'price' => 299.4, 'quality' => 2, 'card_type' => 'chinatelecom']
         ],
-//        500 => [
-//            ['goods_id' => 7841, 'price' => 499, 'quality' => 2, 'card_type' => 'chinamobile'],
+        500 => [
+            ['goods_id' => 7841, 'price' => 501.5, 'quality' => 2, 'card_type' => 'chinamobile'],
 //            ['goods_id' => 7841, 'price' => 499, 'quality' => 2, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7841, 'price' => 499, 'quality' => 2, 'card_type' => 'chinatelecom']
-//        ]
+        ]
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -6332,6 +6332,133 @@ $dazhanggui_phone = ['name' => 'dazhanggui', 'store_id' => 233, 'qualitys' => '1
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
+$yezi_hf_phone = ['name' => 'yezi_hf', 'store_id' => 234, 'qualitys' => '1',
+    'amount' => [
+        10 => [
+            ['goods_id' => 7955, 'price' => 9.65, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7955, 'price' => 9.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7955, 'price' => 9.6, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        20 => [
+            ['goods_id' => 7956, 'price' => 19.3, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7956, 'price' => 19.2, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7956, 'price' => 19.2, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        30 => [
+            ['goods_id' => 7957, 'price' => 28.95, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7957, 'price' => 28.8, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7957, 'price' => 28.8, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        50 => [
+            ['goods_id' => 7958, 'price' => 48.25, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7958, 'price' => 48, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7958, 'price' => 48, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 7959, 'price' => 96.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7959, 'price' => 96, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7959, 'price' => 96, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 7960, 'price' => 193, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7960, 'price' => 192, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7960, 'price' => 192, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        300 => [
+            ['goods_id' => 7961, 'price' => 289.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7961, 'price' => 288, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7961, 'price' => 288, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        500 => [
+            ['goods_id' => 7962, 'price' => 482.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7962, 'price' => 480, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7962, 'price' => 480, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
+$weixue_phone = ['name' => 'weixue', 'store_id' => 235, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 7963, 'price' => 9.67, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7963, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinaunicom']
+//        ],
+//        20 => [
+//            ['goods_id' => 7964, 'price' => 19.34, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7964, 'price' => 19, 'quality' => 1, 'card_type' => 'chinaunicom']
+//        ],
+        30 => [
+            ['goods_id' => 7965, 'price' => 29.01, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7965, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ],
+        50 => [
+            ['goods_id' => 7966, 'price' => 48.35, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7966, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ],
+        100 => [
+            ['goods_id' => 7967, 'price' => 96.7, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7967, 'price' => 95, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ],
+        200 => [
+            ['goods_id' => 7968, 'price' => 193.4, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 7968, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ],
+//        300 => [
+//            ['goods_id' => 7969, 'price' => 290.1, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7969, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom']
+//        ],
+//        500 => [
+//            ['goods_id' => 7970, 'price' => 483.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7970, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom']
+//        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
+$dazhanggui_high_phone = ['name' => 'dazhanggui_high', 'store_id' => 236, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 7971, 'price' => 9.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7971, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7971, 'price' => 9.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 7972, 'price' => 19.2, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7972, 'price' => 19, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7972, 'price' => 19, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        30 => [
+//            ['goods_id' => 7973, 'price' => 28.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7973, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7973, 'price' => 28.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        50 => [
+            ['goods_id' => 7974, 'price' => 48.75, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7974, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7974, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 7975, 'price' => 97.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7975, 'price' => 95, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7975, 'price' => 95, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 7976, 'price' => 195, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7976, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7976, 'price' => 190, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 7977, 'price' => 288, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7977, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7977, 'price' => 285, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 7978, 'price' => 480, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7978, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7978, 'price' => 475, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
 $phone_providers = [
 //    ['name' => 'beixt', 'cfg' => $beixt_phone],
 //    ['name' => 'bxtwt', 'cfg' => $bxtwt_phone],
@@ -6526,7 +6653,9 @@ $phone_providers = [
     ['name' => 'ziyugui', 'cfg' => $ziyugui_phone],
     ['name' => 'guitong_yi', 'cfg' => $guitong_yi_phone],
     ['name' => 'dazhanggui', 'cfg' => $dazhanggui_phone],
-
+    ['name' => 'yezi_hf', 'cfg' => $yezi_hf_phone],
+    ['name' => 'weixue', 'cfg' => $weixue_phone],
+    ['name' => 'dazhanggui_high', 'cfg' => $dazhanggui_high_phone],
 ];
 $config['phone_providers'] = $phone_providers;
 
@@ -6579,4 +6708,4 @@ $third_providers = [
 $config['third_providers'] = $third_providers;
 
 $config['auto_find_channels'] = true;
-$config['cancel_retry_time'] = [10120 => ["9:00",'10:00','11:00']];
+$config['cancel_retry_time'] = [10120 => ["9:00",'10:00','11:00']];

+ 1 - 1
data/logic/buy_virtual.logic.php

@@ -86,7 +86,7 @@ class buy_virtualLogic
      * @param int $member_id
      * @return array
      */
-    public function buyStep3($post, $member_id,$calc_vorder_amount = null,$merchant = false,$use_trans = true)
+    public function buyStep3($post, $member_id, $calc_vorder_amount = null, $merchant = false, $use_trans = true)
     {
         $fRefill = $merchant;
         $result = $this->getBuyStepData($post['goods_id'], $post['quantity'], $member_id, $fRefill);

+ 8 - 2
data/model/predeposit.model.php

@@ -484,12 +484,18 @@ class predepositModel extends Model {
         if (!$update) {
             throw new Exception('操作失败');
         }
+
+        if(defined('SUPPORT_UNUSE_PDLOG') && SUPPORT_UNUSE_PDLOG === true) {
+            return true;
+        }
+
         $insert = $this->table('pd_log')->insert($data_log);
         if (!$insert) {
             throw new Exception('操作失败');
         }
 
-        if(!$fRefill) {
+        if(!$fRefill)
+        {
             // 支付成功发送买家消息
             $param = [];
             $param['code'] = 'predeposit_change';
@@ -498,8 +504,8 @@ class predepositModel extends Model {
             $data_msg['freeze_amount'] = ncPriceFormat($data_msg['freeze_amount']);
             $param['param'] = $data_msg;
             QueueClient::push('sendMemberMsg', $param);
+            return $insert;
         }
-        return $insert;
     }
 
     /**

+ 15 - 0
docker/compose/homecuda/plot/docker-compose.yml

@@ -0,0 +1,15 @@
+version: "3.7"
+
+services:
+  flasksrv:
+    image: pycpu:3.7.10
+    ports:
+      - "5000:5000"
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /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']

+ 0 - 106
docker/compose/homecuda/stat/docker-compose.yml

@@ -1,106 +0,0 @@
-version: "3.7"
-
-services:
-  readersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/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', '-h', '192.168.3.104', '-p', '6379']
-
-  mchreadersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mchreader"
-    command: ['python','mchreader.py', '-h', '192.168.3.104', '-p', '6379']
-
-  speedreader:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-speedreader"
-    command: ['python','speed_reader.py', '-h', '192.168.3.104', '-p', '6379']
-    deploy:
-      resources:
-        limits:
-          cpus: '8'
-
-  chspeed:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-chspeed"
-    command: ['python','chspeed.py','-h', '192.168.3.104', '-p', '6379']
-
-  ratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-ratio"
-    command: ['python','ratio.py', '-h', '192.168.3.104', '-p', '6379']
-
-  flasksrv:
-    image: pycpu:3.7.10
-    ports:
-      - "5000:5000"
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/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']
-
-  mratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratio"
-    command: ['python','mratio.py','-h', '192.168.3.104', '-p', '6379']
-
-  mratios:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratios"
-    command: ['python','mratios.py','-h', '192.168.3.104', '-p', '6379']
-
-  mcounts:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mcounts"
-    command: ['python','mcounts.py','-h', '192.168.3.104', '-p', '6379']

+ 11 - 0
docker/compose/homecuda/statcalc/docker-compose.yml

@@ -23,6 +23,17 @@ services:
     container_name: "panda-mpratios"
     command: ['python','mprofit_ratio.py', '-h', '192.168.3.104', '-p', '6379']
 
+  mtimesratios:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /mnt/upload:/var/www/html/data/upload
+      - /mnt/shoplog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "panda-mtimesratios"
+    command: [ 'python','mtimesratio.py', '-h', '192.168.3.104', '-p', '6379' ]
+
   chspeedratio:
     image: pycpu:3.7.10
     volumes:

+ 19 - 0
docker/compose/workcuda/database/docker-compose.yml

@@ -0,0 +1,19 @@
+version: "3.7"
+
+services:
+  mysql:
+    image: mysql:latest
+    ports:
+      - 3306:3306
+    volumes:
+      - /mnt/mysql/logs:/var/log/mysql
+      - /mnt/mysql/data:/var/lib/mysql
+      - /mnt/mysql/conf/my.cnf:/etc/my.cnf
+    container_name: docker-mysqld
+    restart: always
+    environment:
+      MYSQL_ROOT_PASSWORD: 55668899
+    deploy:
+      resources:
+        limits:
+          cpus: '16'

+ 0 - 106
docker/compose/workcuda/stat/docker-compose.yml

@@ -1,106 +0,0 @@
-version: "3.7"
-
-services:
-  readersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/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', '-h', '192.168.1.83', '-p', '6379']
-
-  mchreadersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mchreader"
-    command: ['python','mchreader.py', '-h', '192.168.1.83', '-p', '6379']
-
-  speedreader:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-speedreader"
-    command: ['python','speed_reader.py', '-h', '192.168.1.83', '-p', '6379']
-    deploy:
-      resources:
-        limits:
-          cpus: '8'
-
-  chspeed:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-chspeed"
-    command: ['python','chspeed.py','-h', '192.168.1.83', '-p', '6379']
-
-  ratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-ratio"
-    command: ['python','ratio.py', '-h', '192.168.1.83', '-p', '6379']
-
-  flasksrv:
-    image: pycpu:3.7.10
-    ports:
-      - "5000:5000"
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/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']
-
-  mratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratio"
-    command: ['python','mratio.py','-h', '192.168.1.83', '-p', '6379']
-
-  mratios:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratios"
-    command: ['python','mratios.py','-h', '192.168.1.83', '-p', '6379']
-
-  mcounts:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mcounts"
-    command: ['python','mcounts.py','-h', '192.168.1.83', '-p', '6379']

+ 2 - 2
docker/compose/workcuda/statcalc/docker-compose.yml

@@ -10,7 +10,7 @@ services:
       - /mnt/shoplog:/var/www/html/data/log
       - /mnt/stdata:/var/www/html/data/stdata
     container_name: "panda-mamount"
-    command: [ 'python','mamount_lack.py', '-h', '192.168.3.46', '-p', '6379' ]
+    command: [ 'python','mamount_lack.py', '-h', '192.168.3.226', '-p', '6379' ]
 
   mpratios:
     image: pycpu:3.7.10
@@ -21,4 +21,4 @@ services:
       - /mnt/shoplog:/var/www/html/data/log
       - /mnt/stdata:/var/www/html/data/stdata
     container_name: "panda-mpratios"
-    command: [ 'python','mprofit_ratio.py', '-h', '192.168.3.46', '-p', '6379' ]
+    command: [ 'python','mprofit_ratio.py', '-h', '192.168.3.226', '-p', '6379' ]

+ 1 - 1
docker/compose/workcuda/statwriter/docker-compose.yml

@@ -10,7 +10,7 @@ services:
       - /mnt/shoplog:/var/www/html/data/log
       - /mnt/stdata:/var/www/html/data/stdata
     container_name: "panda-qreader"
-    command: ['python','qreader.py','-h', '192.168.3.46', '-p', '6379']
+    command: ['python','qreader.py','-h', '192.168.3.226', '-p', '6379']
     deploy:
       resources:
         limits:

+ 20 - 1
docker/compose/xiaoyu/admin/docker-compose.yml

@@ -10,6 +10,7 @@ services:
       - ../conf/etc/localtime:/etc/localtime:ro
       - ../conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
       - ../../../../data/upload:/var/www/html/data/upload
+      - ../../../../chinatelecom:/var/www/html/chinatelecom
     container_name: "panda-nginx"
     command: [nginx,'-g','daemon off;']
 
@@ -85,4 +86,22 @@ services:
 #      - ../../../../data/upload:/var/www/html/data/upload
 #      - ../../../../data/log:/var/www/html/data/log
 #    container_name: "panda-token-refresh"
-#    command: [ php,"/var/www/html/crontab/index.php",'vendor','token_refresh' ]
+#    command: [ php,"/var/www/html/crontab/index.php",'vendor','token_refresh' ]
+
+  vapisrv:
+    image: php-zts:7.3.18
+    ports:
+      - 9103:9103
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - ../conf/php/php.ini:/usr/local/etc/php/php.ini
+      - ../../../../data/upload:/var/www/html/data/upload
+      - ../../../../data/log:/var/www/html/data/log
+      - ../conf/php/vapi-spwan-start:/usr/local/bin/docker-spwan-start
+    container_name: "panda-vapi"
+    command: [ 'docker-spwan-start' ]
+    deploy:
+      resources:
+        limits:
+          cpus: '8'

+ 9 - 0
docker/compose/xiaoyu/conf/nginx/nginx.conf

@@ -70,6 +70,15 @@ http
             include fastcgi_params;
         }
 
+        location ~ /vapi/[/\w]+\.php$ {
+            root           $folder_name;
+            fastcgi_pass   vapisrv:9103;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  $folder_name$fastcgi_script_name;
+            fastcgi_param  SIGN $http_sign;
+            include fastcgi_params;
+        }
+
         location ~ \.php$ {
 	        add_header Cache-Control no-store;
             root           $folder_name;

+ 11 - 0
docker/compose/xiaoyu/conf/php/vapi-spwan-start

@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+spawn-fcgi -a 0.0.0.0 -p 9103 -F 16 -f "php /var/www/html/vapi/vapi.php"
+
+time=$(date "+%Y%m%d")
+
+if [ ! -f "/var/www/html/data/log/${time}-vapi.log" ]; then
+    touch "/var/www/html/data/log/${time}-vapi.log"
+fi
+
+tail -f "/var/www/html/data/log/${time}-vapi.log"

+ 15 - 0
docker/compose/xyz/plot/docker-compose.yml

@@ -0,0 +1,15 @@
+version: "3.7"
+
+services:
+  flasksrv:
+    image: pycpu:3.7.10
+    ports:
+      - "5000:5000"
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /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']

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

@@ -1,106 +0,0 @@
-version: "3.7"
-
-services:
-  readersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /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', '-h', '172.26.105.125', '-p', '6379']
-
-  mchreadersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mchreader"
-    command: ['python','mchreader.py', '-h', '172.26.105.125', '-p', '6379']
-
-  speedreader:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-speedreader"
-    command: ['python','speed_reader.py', '-h', '172.26.105.125', '-p', '6379']
-    deploy:
-      resources:
-        limits:
-          cpus: '8'
-
-  chspeed:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-chspeed"
-    command: ['python','chspeed.py','-h', '172.26.105.125', '-p', '6379']
-
-  ratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-ratio"
-    command: ['python','ratio.py', '-h', '172.26.105.125', '-p', '6379']
-
-  flasksrv:
-    image: pycpu:3.7.10
-    ports:
-      - "5000:5000"
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /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']
-
-  mratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratio"
-    command: ['python','mratio.py','-h', '172.26.105.125', '-p', '6379']
-
-  mratios:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mratios"
-    command: ['python','mratios.py','-h', '172.26.105.125', '-p', '6379']
-
-  mcounts:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "panda-mcounts"
-    command: ['python','mcounts.py','-h', '172.26.105.125', '-p', '6379']

+ 10 - 0
docker/compose/xyz/statcalc/docker-compose.yml

@@ -21,6 +21,16 @@ services:
     container_name: "panda-mpratios"
     command: ['python','mprofit_ratio.py', '-h', '172.26.105.125', '-p', '6379']
 
+  mtimesratios:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /mnt/shoplog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "panda-mtimesratios"
+    command: [ 'python','mtimesratio.py', '-h', '172.26.105.125', '-p', '6379' ]
+
   chspeedratio:
     image: pycpu:3.7.10
     volumes:

+ 0 - 95
docker/compose/xyzt/tstat/docker-compose.yml

@@ -1,95 +0,0 @@
-version: "3.7"
-
-services:
-  readersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/testlog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-reader"
-    command: ['python','reader.py', '-h', '172.26.105.127', '-p', '6379']
-
-  mchreadersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-mchreader"
-    command: ['python','mchreader.py', '-h', '172.26.105.127', '-p', '6379']
-
-  speedreader:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-speedreader"
-    command: ['python','speed_reader.py', '-h', '172.26.105.127', '-p', '6379']
-    deploy:
-      resources:
-        limits:
-          cpus: '8'
-
-  ratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/testlog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-ratio"
-    command: ['python','ratio.py', '-h', '172.26.105.127', '-p', '6379']
-
-  flasksrv:
-    image: pycpu:3.7.10
-    ports:
-      - "5000:5000"
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/testlog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-flask"
-    command: ['python','app.py']
-
-  mratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/testlog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-mratio"
-    command: ['python','mratio.py','-h', '172.26.105.127', '-p', '6379']
-
-  mcounts:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-mcounts"
-    command: ['python','mcounts.py','-h', '172.26.105.127', '-p', '6379']
-
-  chspeed:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /nfs/upload:/var/www/html/data/upload
-      - /mnt/shoplog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "test-chspeed"
-    command: ['python','chspeed.py','-h', '172.26.105.127', '-p', '6379']

+ 0 - 78
docker/compose/yl/ylstat/docker-compose.yml

@@ -1,78 +0,0 @@
-version: "3.7"
-
-services:
-  readersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-reader"
-    command: ['python','reader.py', '-h', '172.26.80.7', '-p', '6379']
-
-  mchreadersrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-mchreader"
-    command: ['python','mchreader.py', '-h', '172.26.80.7', '-p', '6379']
-
-  speedreader:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-speedreader"
-    command: ['python','speed_reader.py', '-h', '172.26.80.7', '-p', '6379']
-    deploy:
-      resources:
-        limits:
-          cpus: '8'
-
-  flasksrv:
-    image: pycpu:3.7.10
-    ports:
-      - "5000:5000"
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-flask"
-    command: ['python','app.py']
-
-  mratiosrv:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-mratio"
-    command: ['python','mratio.py','-h', '172.26.80.7', '-p', '6379']
-
-  mratios:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-mratios"
-    command: ['python','mratios.py','-h', '172.26.80.7', '-p', '6379']
-
-  mcounts:
-    image: pycpu:3.7.10
-    volumes:
-      - ../../../../:/var/www/html
-      - ../conf/etc/localtime:/etc/localtime:ro
-      - /mnt/yllog:/var/www/html/data/log
-      - /mnt/stdata:/var/www/html/data/stdata
-    container_name: "yl-mcounts"
-    command: ['python','mcounts.py','-h', '172.26.80.7', '-p', '6379']

+ 10 - 0
docker/compose/yl/ylstatcalc/docker-compose.yml

@@ -22,6 +22,16 @@ services:
     container_name: "yl-mpratios"
     command: ['python','mprofit_ratio.py', '-h', '172.26.80.7', '-p', '6379']
 
+  mtimesratios:
+    image: pycpu:3.7.10
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /mnt/yllog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "yl-mtimesratios"
+    command: [ 'python','mtimesratio.py', '-h', '172.26.80.7', '-p', '6379' ]
+
   chspeedratio:
     image: pycpu:3.7.10
     volumes:

+ 67 - 48
helper/refill/RefillBase.php

@@ -26,8 +26,6 @@ use Swoole;
 class RefillBase
 {
     protected $mPolicy;
-
-    protected $mLimits = [];
     protected function __construct($policy)
     {
         $this->mPolicy = $policy;
@@ -101,7 +99,7 @@ class RefillBase
             return (substr($haystack, 0, $length) === $needle);
         };
 
-        $headers = ['0095', 'SP', 'J98', 'WX'];
+        $headers = ['0095', 'SP', 'J98', 'WX', '11010336J'];
         $spcheker = function () use ($start_with, $headers, $official_sn)
         {
             $official_sn = strtoupper($official_sn);
@@ -214,7 +212,6 @@ class RefillBase
         catch (Exception $ex) {
             $tran->rollback();
             Log::record("Error:" . $ex->getMessage(), Log::ERR);
-
             Swoole\Coroutine::sleep(5);
             util::push_notify($chname,$input);
             return false;
@@ -304,7 +301,7 @@ class RefillBase
         $input['pd_pay'] = true;
 
         $logic_buy_virtual = Logic('buy_virtual');
-        $result = $logic_buy_virtual->buyStep3($input, $buyer_id, [$calc, 'calc_vorder_amount'], true,false);
+        $result = $logic_buy_virtual->buyStep3($input, $buyer_id, [$calc, 'calc_vorder_amount'], true, true);
 
         $mod_refill = Model('refill_order');
         if ($result['state'] === true)
@@ -726,64 +723,86 @@ class RefillBase
 
     public function query_net($order_id)
     {
+        $query_handler = function ($order_id, $order_info, $state, $order_state, $chname)
+        {
+            $mod_refill = Model('refill_order');
+            if ($order_info['order_state'] == ORDER_STATE_PAY) {
+                $query_able = true;
+            } else {
+                $query_able = false;
+            }
+
+            $can_try = false;
+            if($query_able)
+            {
+                if(!$state) {
+                    QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
+                    $neterr = true;
+                }
+                elseif($order_state == ORDER_STATE_SUCCESS || $order_state == ORDER_STATE_CANCEL)
+                {
+                    $neterr = false;
+                    $logic_vr_order = Logic("vr_order");
+                    $logic_vr_order->changeOrderStateSend($order_id, true);
+
+                    $data = ['commit_time' => time()];
+                    $mod_refill->edit($order_id, $data);
+                    QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
+                }
+                elseif ($order_state == ORDER_STATE_NOEXIST) {
+                    $neterr = false;
+                    $logic_vr_order = Logic("vr_order");
+                    $logic_vr_order->changeOrderStateSend($order_id, true);
+                    $can_try = true;
+                }
+                else {
+                    $neterr = true;
+                    QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
+                }
+
+                util::monitor_netchk($chname,$neterr);
+            }
+
+            return [true,$can_try];
+        };
+
         $mod_order = Model('vr_order');
         $order_info = $mod_order->getOrderInfo(['order_id' => $order_id]);
-
-        if(empty($order_info)) return false;
+        if (empty($order_info) || $order_info['order_state'] != ORDER_STATE_PAY) return false;
 
         $mod_refill = Model('refill_order');
         $refill_info = $mod_refill->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
         $chname = $refill_info['channel_name'];
-        $mchid = $refill_info['mchid'];
-        $mch_order = $refill_info['mch_order'];
+        $provider = $this->mPolicy->provider($chname);
+        if(empty($provider)) return false;
 
-        if($order_info['order_state'] == ORDER_STATE_PAY) {
-            $query_able = true;
+        [$state, $order_state] = $provider->query($refill_info);
+
+        try {
+            $can_try = false;
+            $tran = new trans_wapper($mod_order, 'query_net change order state trans');
+            $order_info = $mod_order->getOrderInfo(['order_id' => $order_id], '*', true, true);
+            [$ret, $can_try] = $query_handler($order_id, $order_info, $state, $order_state, $chname);
+            $tran->commit();
+            $trans_succ = true;
         }
-        else {
-            $query_able = false;
+        catch (Exception $ex) {
+            Log::record("Error:" . $ex->getMessage(), Log::ERR);
+            $trans_succ = false;
+            $tran->rollback();
+            $ret = false;
         }
 
-        if($query_able)
+        if($can_try)
         {
-            if(empty($chname)) return false;
-
-            $provider = $this->mPolicy->provider($chname);
-            if(empty($provider)) return false;
-
-            [$state, $order_state] = $provider->query($refill_info);
-            if(!$state) {
-                QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
-                $neterr = true;
-            }
-            elseif($order_state == ORDER_STATE_SUCCESS || $order_state == ORDER_STATE_CANCEL)
-            {
-                $neterr = false;
-                $logic_vr_order = Logic("vr_order");
-                $logic_vr_order->changeOrderStateSend($order_id, true);
-
-                $data = ['commit_time' => time()];
-                $mod_refill->edit($order_id, $data);
-                QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
-            }
-            elseif ($order_state == ORDER_STATE_NOEXIST) {
-                $neterr = false;
-                $logic_vr_order = Logic("vr_order");
-                $logic_vr_order->changeOrderStateCancel($order_info, '', "{$chname}查询订单不存在.",true,true);
-
-                $mod_refill->edit($order_id, ['notify_time' => time(), 'notify_state' => 1]);
-                util::pop_queue_order($mchid,$mch_order);
-                QueueClient::push("NotifyMerchantComplete", ['order_id' => $order_id, 'manual' => false]);
-            }
-            else {
-                $neterr = true;
+            if($trans_succ) {
+                $this->proc_notify($order_id, false, true, $chname);
+            } else {
                 QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
             }
-
-            util::monitor_netchk($chname,$neterr);
         }
 
-        return true;
+        return $ret;
     }
 
     public function manual_success($order_id)

+ 50 - 0
helper/refill/api/xyz/dazhanggui_high/RefillCallBack.php

@@ -0,0 +1,50 @@
+<?php
+namespace refill\dazhanggui_high;
+
+require_once(BASE_HELPER_RAPI_PATH . '/dazhanggui_high/config.php');
+
+use refill;
+class RefillCallBack implements refill\IRefillCallBack
+{
+    public function verify($params): bool
+    {
+        $sign = $this->sign($params);
+        if ($params['szVerifyString'] == $sign) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$userid}&szOrderId={$params['szOrderId']}&szPhoneNum={$params['szPhoneNum']}&nDemo={$params['nDemo']}&fSalePrice={$params['fSalePrice']}";
+        $content .= "&nFlag={$params['nFlag']}&szKey={$key}";
+        return md5($content);
+    }
+
+    public function notify($params)
+    {
+        $status = intval($params['nFlag']);
+        $order_sn = $params['szOrderId'];
+        $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false,false];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $data['official_sn'] = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false,true];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true,true];
+        }
+        else {
+            return [$order_id, false, false,false];
+        }
+    }
+}

+ 142 - 0
helper/refill/api/xyz/dazhanggui_high/RefillPhone.php

@@ -0,0 +1,142 @@
+<?php
+
+namespace refill\dazhanggui_high;
+
+require_once(BASE_HELPER_RAPI_PATH . '/dazhanggui_high/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $phone, int $amount, int $card_type, string $order_sn)
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $params['szOrderId'] = $order_sn;
+        $params['szPhoneNum'] = $phone;
+        $params['nMoney'] = $amount;
+        $params['nSortType'] = config::operator[$card_type];
+        $params['szProductId'] = config::Product[$card_type][$amount];
+        $params['nProductClass'] = 1;
+        $params['nProductType'] = 1;
+        $params['szTimeStamp'] = date("Y-m-d H:i:s");
+        $params['szNotifyUrl'] = config::NOTIFY_URL;
+        return $params;
+    }
+
+    public function add($card_no, $card_type, $amount, $params,&$net_errno = 0)
+    {
+        $order_sn = $params['order_sn'];
+        $params = $this->req_params($card_no, $amount, $card_type, $order_sn);
+
+        $sign = $this->sign($params);
+        $params['szVerifyString'] = $sign;
+
+        $resp = http_request(config::ORDER_URL, $params, 'POST', false, config::ExtHeaders, $net_errno);
+
+        if (empty($resp)) {
+            return [false, '网络错误', true];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+
+            $nRtn = $resp['nRtn'];
+            if (empty($resp)) {
+                return [false, '网络错误', true];
+            } elseif ($nRtn === 0) {
+                return [true, '', false];
+            } elseif (in_array($nRtn, config::ERR_NOS, true)) {
+                return [false, $resp['szRtnCode'], false];
+            } elseif (in_array($nRtn, [2050, 999], true)) {
+                $net_errno = "HTTP-{$nRtn}";
+                return [false, $resp['szRtnCode'], true];
+            } else {
+                $err = 998;
+                $net_errno = "HTTP-{$err}";
+                return [false, $resp['szRtnCode'], true];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $params['szOrderId'] = $refill_info['order_sn'];
+        $key = config::KEY;
+        $content = "szAgentId={$params['szAgentId']}&szOrderId={$params['szOrderId']}&szKey={$key}";
+        $params['szVerifyString'] = md5($content);
+
+        $resp = http_request(config::QUERY_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            }
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $updata['official_sn'] = $resp['szRtnMsg'];
+                Model('refill_order')->edit($refill_info['order_id'], $updata);
+                $order_state = ORDER_STATE_SUCCESS;
+            } elseif ($status === 5013) {
+                $order_state = ORDER_STATE_CANCEL;
+            } elseif (in_array($status, [5011,5019],true)) {
+                $order_state = ORDER_STATE_SEND;
+            } elseif ($status === 5005 && (time() - $refill_info['commit_time'] >= 300)) {
+                $order_state = ORDER_STATE_NOEXIST;
+            } else {
+                return [false, $resp['szRtnMsg']];
+            }
+
+            return [true, $order_state];
+        }
+    }
+
+    public function balance()
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$params['szAgentId']}&szKey={$key}";
+        $params['szVerifyString'] = md5($content);
+
+        $resp = http_request(config::BALANCE_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            } elseif ($resp['nRtn'] === 0) {
+                return [true, $resp['fBalance']];
+            } else {
+                return [false, $resp['szRtnCode']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$userid}&szOrderId={$params['szOrderId']}&szPhoneNum={$params['szPhoneNum']}&nMoney={$params['nMoney']}&nSortType={$params['nSortType']}";
+        $content .= "&nProductClass={$params['nProductClass']}&nProductType={$params['nProductType']}&szTimeStamp={$params['szTimeStamp']}&szKey={$key}";
+        return md5($content);
+    }
+}

+ 15 - 0
helper/refill/api/xyz/dazhanggui_high/api.txt

@@ -0,0 +1,15 @@
+登录账号:yzgj01
+登录密码:123456
+话费下单地址:http://47.101.136.81:10186/plat/api/old/submitorder
+查询地址:http://47.101.136.81:10186/plat/api/old/queryorder
+查询余额地址:http://47.101.136.81:10186/plat/api/old/queryBalance
+
+正式ID:	200021
+秘钥: fb943af92a7849c0b0e0f4ba1c13158a
+
+后台登录地址:http://47.101.136.81:10186/plat/index
+对接文档地址:https://docs.qq.com/doc/DWkV1VkxQVk13eEtQ
+
+全国移动50元	1000050
+全国移动100元	1000100
+全国移动200元	1000200

+ 35 - 0
helper/refill/api/xyz/dazhanggui_high/config.php

@@ -0,0 +1,35 @@
+<?php
+
+
+namespace refill\dazhanggui_high;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://47.101.136.81:10186/plat/api/old/submitorder';
+    const QUERY_URL= 'http://47.101.136.81:10186/plat/api/old/queryorder';
+    const BALANCE_URL = 'http://47.101.136.81:10186/plat/api/old/queryBalance';
+
+    const USER_ID= '200021';
+    const KEY = 'fb943af92a7849c0b0e0f4ba1c13158a';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_dazhanggui_high.php";
+
+    const operator = [
+        mtopcard\ChinaMobileCard  => 1,
+        mtopcard\ChinaUnicomCard  => 2,
+        mtopcard\ChinaTelecomCard => 3
+    ];
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
+
+    const ERR_NOS = [
+        1000,1001,1003,1004,2001,2002,2003,2020,2021,1006,2030,3003
+    ];
+
+    const Product = [
+        mtopcard\ChinaMobileCard => [
+            50  => 1000050,
+            100 => 1000100,
+            200 => 1000200,
+        ]
+    ];
+}

BIN
helper/refill/api/xyz/guochuang/20220826广东移动调价函.png


BIN
helper/refill/api/xyz/guochuang/20220827广东移动调价函.png


BIN
helper/refill/api/xyz/guochuang/20220829山西移动调价函.png


BIN
helper/refill/api/xyz/guochuang/20220830青海移动调价函.png


BIN
helper/refill/api/xyz/guochuang/20220906广东移动调价函.png


+ 4 - 4
helper/refill/api/xyz/guochuang/config.php

@@ -67,12 +67,12 @@ class config
         "4-10-6" => 9.825, "4-20-6" => 19.65, "4-30-6" => 29.475, "4-50-6" => 49.125, "4-100-6" => 98.25, "4-200-6" => 196.5, "4-300-6" => 294.75, "4-500-6" => 491.25,//辽宁 6
         "4-10-9" => 9.94, "4-20-9" => 19.88, "4-30-9" => 29.82, "4-50-9" => 49.7, "4-100-9" => 99.4,//上海 9
         "4-10-8" => 10.03, "4-20-8" => 20.06, "4-30-8" => 30.09, "4-50-8" => 50.15, "4-100-8" => 100.3, "4-200-8" => 200.6, "4-300-8" => 301.2, "4-500-8" => 502,//黑龙江 8
-        "4-10-29" => 9.815, "4-20-29" => 19.63, "4-30-29" => 29.445, "4-50-29" => 49.075, "4-100-29" => 98.15, "4-200-29" => 196.3, "4-300-29" => 294.45, "4-500-29" => 490.75,//青海 29
+        "4-10-29" => 9.86, "4-20-29" => 19.72, "4-30-29" => 29.58, "4-50-29" => 49.3, "4-100-29" => 98.6, "4-200-29" => 197.2, "4-300-29" => 295.8, "4-500-29" => 493,//青海 29
         "4-10-28" => 9.985, "4-20-28" => 19.97, "4-30-28" => 29.955, "4-50-28" => 49.925, "4-100-28" => 99.85, "4-200-28" => 199.7, "4-300-28" => 299.55, "4-500-28" => 499.25,//甘肃 28
         "4-10-13" => 10.22, "4-20-13" => 19.94, "4-30-13" => 29.91, "4-50-13" => 49.85, "4-100-13" => 99.7, "4-200-13" => 199.4, "4-300-13" => 300.9, "4-500-13" => 501.5,//福建 13
         "4-10-5" => 10.035, "4-20-5" => 20.07, "4-30-5" => 30.09, "4-50-5" => 50.15, "4-100-5" => 100.3, "4-200-5" => 200.4, "4-300-5" => 300.6, "4-500-5" => 501,//内蒙古 5
         "4-30-18" => 29.835, "4-50-18" => 49.725, "4-100-18" => 99.45, "4-200-18" => 198.3,//湖南 18
-        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.97, "4-50-19" => 49.95, "4-100-19" => 99.9, "4-200-19" => 199.8, "4-300-19" => 299.7, "4-500-19" => 499.5,//广东 19
+        "4-10-19" => 9.99, "4-20-19" => 19.98, "4-30-19" => 29.88, "4-50-19" => 49.8, "4-100-19" => 99.6, "4-200-19" => 199.2, "4-300-19" => 298.8, "4-500-19" => 498,//广东 19
         "4-10-7" => 9.93, "4-20-7" => 19.86, "4-30-7" => 29.52, "4-50-7" => 49.2, "4-100-7" => 98.4, "4-200-7" => 196.8, "4-300-7" => 295.2, "4-500-7" => 492,//吉林 7
         "4-10-1" => 10.31, "4-20-1" => 20.32, "4-30-1" => 30.33, "4-50-1" => 50.35, "4-100-1" => 100.4, "4-200-1" => 200.3, "4-300-1" => 300.45, "4-500-1" => 500.75,//北京 1
         "4-10-22" => 10.015, "4-20-22" => 20.03, "4-30-22" => 30.045, "4-50-22" => 50.075, "4-100-22" => 100.15, "4-200-22" => 200.3, "4-300-22" => 300.45, "4-500-22" => 500.75,//重庆 22
@@ -81,7 +81,7 @@ class config
         "4-10-11" => 9.945, "4-20-11" => 19.89, "4-30-11" => 29.835, "4-50-11" => 49.725, "4-100-11" => 99.45, "4-200-11" => 198.9, "4-300-11" => 298.35, "4-500-11" => 497.25,//浙江 11
         "4-10-17" => 9.945, "4-20-17" => 19.89, "4-30-17" => 29.835, "4-50-17" => 49.725, "4-100-17" => 99.45, "4-200-17" => 198.9, "4-300-17" => 298.35, "4-500-17" => 497.25,//湖北 17
         "4-10-16" => 10.24, "4-20-16" => 20.28, "4-30-16" => 30.3, "4-50-16" => 50.35, "4-100-16" => 100.4, "4-200-16" => 200.8, "4-300-16" => 301.2, "4-500-16" => 502,//河南 16
-        "4-50-4" => 49.75, "4-100-4" => 99.5, "4-200-4" => 199,//山西 4
+        "4-10-4" => 10.3, "4-20-4" => 20.6, "4-30-4" => 30.9, "4-50-4" => 50.1, "4-100-4" => 100.2, "4-200-4" => 200.4, "4-300-4" => 300.6, "4-500-4" => 501,//山西 4
         "4-10-24" => 10.18, "4-20-24" => 20.18, "4-30-24" => 30.21, "4-50-24" => 50.1, "4-100-24" => 100.2, "4-200-24" => 200.4, "4-300-24" => 300.6, "4-500-24" => 501,//贵州 24
         "4-10-30" => 10.12, "4-20-30" => 20.24, "4-30-30" => 30.129, "4-50-30" => 50.15, "4-100-30" => 100.2, "4-200-30" => 200.4, "4-300-30" => 300.3, "4-500-30" => 500.5,//宁夏 30
         "4-10-25" => 10.14, "4-20-25" => 20.2, "4-30-25" => 30.18, "4-50-25" => 50.1, "4-100-25" => 100.2, "4-200-25" => 200.4, "4-300-25" => 300.6, "4-500-25" => 501,//云南 25
@@ -99,4 +99,4 @@ class config
         "6-10-15" => 10.21, "6-20-15" => 20.22, "6-30-15" => 30.231, "6-50-15" => 50.25, "6-100-15" => 100.3, "6-200-15" => 200.3, "6-300-15" => 300.45, "6-500-15" => 500.75,//山东 15
         "6-10-12" => 10.04, "6-20-12" => 20.05, "6-30-12" => 30.12, "6-50-12" => 50.2, "6-100-12" => 100.4, "6-200-12" => 200.6, "6-300-12" => 300.9, "6-500-12" => 501.5,//安徽 12
     ];
-}
+}

+ 11 - 30
helper/refill/api/xyz/ruixunda/RefillCallBack.php

@@ -8,9 +8,7 @@ class RefillCallBack implements refill\IRefillCallBack
 {
     public function verify($params): bool
     {
-        $input = $params;
-        unset($input['sign']);
-        $sign = $this->sign($input);
+        $sign = $this->sign($params);
         if ($params['sign'] == $sign) {
             return true;
         } else {
@@ -20,45 +18,28 @@ class RefillCallBack implements refill\IRefillCallBack
 
     private function sign($params)
     {
-        $params['appSecret'] = config::APP_SECRET;
-        ksort($params);
-        $content = '';
-        foreach ($params as $key => $value) {
-            if($this->check_empty($value) === false) {
-                $content .= "{$key}={$value}&";
-            }
-        }
-        $content = rtrim($content, '&');
-        return md5($content);
-    }
-
-    private function check_empty($value)
-    {
-        if (!isset($value))
-            return true;
-        if ($value === null)
-            return true;
-        if (trim($value) === "")
-            return true;
-
-        return false;
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&orderid={$params['orderid']}&sporderid={$params['sporderid']}&merchantsubmittime={$params['merchantsubmittime']}";
+        $content .= "&resultno={$params['resultno']}&key={$key}";
+        return strtoupper(md5($content));
     }
 
     public function notify($params)
     {
-        $status = intval($params['orderStatus']);
-        $order_sn = $params['outOrderId'];
+        $status = intval($params['resultno']);
+        $order_sn = $params['sporderid'];
         $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
         if (empty($order_info)) {
             return [false, false, false,false];
         }
 
         $order_id = $order_info['order_id'];
-        if ($status === 2) {
-            $data['official_sn'] = strtolower($params['ext1']) == 'null' ? '' : $params['ext1'];
+        if ($status === 1) {
+            $data['official_sn'] = strtolower($params['remark1']) == 'null' ? '' : $params['remark1'];
             Model('refill_order')->edit($order_id, $data);
             return [$order_id, true, false, true];
-        } elseif ($status === 3) {
+        } elseif ($status === 9) {
             return [$order_id, false, true, true];
         } else {
             return [$order_id, false, false, false];

+ 62 - 62
helper/refill/api/xyz/ruixunda/RefillPhone.php

@@ -14,15 +14,18 @@ class RefillPhone extends refill\IRefillPhone
         parent::__construct($cfgs);
     }
 
-    private function req_params(int $phone, int $amount, int $card_type, string $order_sn)
+    private function req_params(int $phone, int $amount, $card_type, string $order_sn)
     {
-        $params['appId'] = config::APP_ID;
-        $params['outOrderId'] = $order_sn;
-        $params['uuid'] = $phone;
-        $params['itemId'] = config::PRODUCT[$card_type][$amount];
-        $params['itemFace'] = $amount;
-        $params['callbackUrl'] = config::NOTIFY_URL;
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
+        $params['userid'] = config::USER_ID;
+        $params['productid'] = config::ProductIdS[$card_type][$amount];
+        $params['price'] = $amount;
+        $params['num'] = 1;
+        $params['mobile'] = $phone;
+        $params['spordertime'] = date("YmdHis");
+        $params['sporderid'] = $order_sn;
+        $params['back_url'] = config::NOTIFY_URL;
+        $params['paytype'] = config::operator[$card_type];
+
         return $params;
     }
 
@@ -30,9 +33,7 @@ class RefillPhone extends refill\IRefillPhone
     {
         $order_sn = $params['order_sn'];
         $params = $this->req_params($card_no, $amount, $card_type, $order_sn);
-        if(empty($params['itemId'])) {
-            return [false, '商品编号错误', false];
-        }
+
         $sign = $this->sign($params);
         $params['sign'] = $sign;
 
@@ -44,29 +45,35 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
+            $resp = $this->xmlToArray($resp);
             if (empty($resp)) {
                 return [false, '网络错误', true];
-            } elseif ($resp['code'] === '00') {
-                return [true, $resp['orderId'], false];
-            } elseif (in_array($resp['code'], config::ERRCODES, true)) {
-                return [false, $resp['msg'], false];
-            } elseif (in_array($resp['code'], ['-22', '-23', '-99'], true)) {
-                $net_errno = "HTTP-{$resp['code']}";
-                return [false, $resp['msg'], true];
+            }
+
+            $resultno = $resp['resultno'];
+            if (in_array($resultno, ['0', '2'], true)) {
+                return [true, $resp['orderid'], false];
+            } elseif (in_array($resultno, config::ERR_NOS, true)) {
+                return [false, $resultno, false];
+            } elseif ($resultno === '9999' || $resultno === '5006') {
+                $net_errno = "HTTP-{$resultno}";
+                return [false, $resultno, true];
             } else {
-                $net_errno = "HTTP-998";
-                return [false, $resp['msg'], true];
+                //未知结果码
+                $err = 998;
+                $net_errno = "HTTP-{$err}";
+                return [false, $resultno, true];
             }
         }
     }
 
     public function query($refill_info)
     {
-        $params['appId'] = config::APP_ID;
-        $params['outOrderId'] = $refill_info['order_sn'];
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
-        $params['sign'] = $this->sign($params);
+        $params['userid'] = config::USER_ID;
+        $params['sporderid'] = $refill_info['order_sn'];
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&sporderid={$params['sporderid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
 
         $resp = http_request(config::QUERY_URL, $params, 'POST', false, config::ExtHeaders);
 
@@ -76,40 +83,39 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
-            if (empty($resp)) {
+            $resp = $this->xmlToArray($resp);
+            if (empty($resp))
+            {
                 return [false, '网络错误'];
             }
-            elseif ($resp['code'] === '00')
+            else
             {
-                $status = $resp['orderStatus'];
-                if ($status === '2') {
-                    $updata['official_sn'] = $resp['ext1'];
+                $resultno = $resp['resultno'];
+                if ($resultno === '1') {
+                    $updata['official_sn'] = $resp['remark1'];
                     Model('refill_order')->edit($refill_info['order_id'], $updata);
                     $order_state = ORDER_STATE_SUCCESS;
-                } elseif ($status === '3') {
+                } elseif ($resultno === '9') {
                     $order_state = ORDER_STATE_CANCEL;
-                } elseif ($status === '1') {
+                } elseif (in_array($resultno, ['0','2'], true)) {
                     $order_state = ORDER_STATE_SEND;
-                } elseif ($status === '4' && (time() - $refill_info['commit_time'] >= 600)) {
+                } elseif ($resultno === '5007' && (time() - $refill_info['commit_time'] > 600)) {
                     $order_state = ORDER_STATE_NOEXIST;
                 } else {
-                    return [false, $resp['msg']];
+                    return [false, $resultno];
                 }
+
                 return [true, $order_state];
             }
-            else
-            {
-                return [false, $resp['msg']];
-            }
         }
     }
 
     public function balance()
     {
-        $params['appId'] = config::APP_ID;
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
-        $params['sign'] = $this->sign($params);
+        $params['userid'] = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
 
         $resp = http_request(config::BALANCE_URL, $params, 'POST', false, config::ExtHeaders);
 
@@ -119,37 +125,31 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
+            $resp = $this->xmlToArray($resp);
             if (empty($resp)) {
                 return [false, '网络错误'];
-            } elseif ($resp['code'] === '00') {
+            } elseif ($resp['resultno'] === '1') {
                 return [true, $resp['balance']];
             } else {
-                return [false, $resp['msg']];
+                return [false, $resp['resultno']];
             }
         }
     }
 
-    /**
-     * 获取毫秒级别的时间戳
-     */
-    private function get_millisecond()
+    private function sign($params)
     {
-        list($usec, $sec) = explode(" ", microtime());
-        return round($usec*1000);
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&productid={$params['productid']}&price={$params['price']}&num={$params['num']}&mobile={$params['mobile']}&spordertime={$params['spordertime']}";
+        $content .= "&sporderid={$params['sporderid']}&key={$key}";
+        return strtoupper(md5($content));
     }
 
-    private function sign($params)
+    public function xmlToArray($xml)
     {
-        $params['appSecret'] = config::APP_SECRET;
-        ksort($params);
-        $content = '';
-        foreach ($params as $key => $value) {
-            if($this->check_empty($value) === false) {
-                $content .= "{$key}={$value}&";
-            }
-        }
-        $content = rtrim($content, '&');
-        return md5($content);
+        $replace_str = str_replace(' ','','encoding="gb2312"');
+        $xml = mb_convert_encoding($xml,"UTF-8","gb2312");
+        $xml = str_replace($replace_str, "encoding='utf-8'", $xml);
+        return refill\util::xmlToArray($xml);
     }
 }

+ 38 - 32
helper/refill/api/xyz/ruixunda/config.php

@@ -6,39 +6,45 @@ namespace refill\ruixunda;
 use mtopcard;
 class config
 {
-    const ORDER_URL = 'http://47.98.117.207:8911/api/hf/order/submit';
-    const QUERY_URL = 'http://47.98.117.207:8911/api/order/query';
-    const BALANCE_URL = 'http://47.98.117.207:8911/api/account/balance';
+    //https://www.showdoc.com.cn/AQL666666/
+    const ORDER_URL = 'http://47.96.69.138:9086/onlinepay.do';
+    const QUERY_URL= 'http://47.96.69.138:9086/searchpay.do';
+    const BALANCE_URL = 'http://47.96.69.138:9086/searchbalance.do';
 
-    const APP_ID = 'HopCzvajlL';
-    const APP_SECRET = 'iLDpqQtdzhOaaNms';
+    const USER_ID= '10002506';
+    const KEY = '2nQfpyw2AJhRPjfsTkCcsMTybiYw2bHD';
     const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_ruixunda.php";
-    const PRODUCT = [
-        mtopcard\ChinaMobileCard => [
-            30  => 7,
-            50  => 8,
-            100 => 9,
-            200 => 10,
-            300 => 11,
-            500 => 12,
-        ],
-        mtopcard\ChinaUnicomCard => [
-            30  => 13,
-            50  => 14,
-            100 => 15,
-            200 => 16,
-            300 => 17,
-            500 => 18,
-        ],
-        mtopcard\ChinaTelecomCard => [
-            30  => 19,
-            50  => 20,
-            100 => 21,
-            200 => 22,
-            300 => 23,
-            500 => 24,
-        ],
+
+    const operator = [
+        mtopcard\ChinaMobileCard  => 'yd',
+        mtopcard\ChinaUnicomCard  => 'lt',
+        mtopcard\ChinaTelecomCard => 'dx'
+    ];
+    const ERR_NOS = [
+        '5001','5002','5003','5004','5005','5008','5009','5010','5011','5012'
+    ];
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;'];
+    const ProductIdS = [
+        mtopcard\ChinaMobileCard =>
+            [
+                30  => '101687',
+                50  => '101688',
+                100 => '101689',
+                200 => '101690',
+            ],
+        mtopcard\ChinaUnicomCard =>
+            [
+                30  => '101705',
+                50  => '101706',
+                100 => '101707',
+                200 => '101708',
+            ],
+        mtopcard\ChinaTelecomCard =>
+            [
+                30  => '101723',
+                50  => '101724',
+                100 => '101725',
+                200 => '101726',
+            ]
     ];
-    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
-    const ERRCODES = ['-10', '-12', '-13', '-14', '-15', '-16', '-18', '-21'];
 }

BIN
helper/refill/api/xyz/ruixunda/云九一商品编码.docx


+ 37 - 0
helper/refill/api/xyz/ruixunda/对接文档-yezi.txt

@@ -0,0 +1,37 @@
+登录名:椰子
+密码:yezi3872
+用户编码:10002506
+密钥:2nQfpyw2AJhRPjfsTkCcsMTybiYw2bHD
+
+
+下游客户注册和登录地址:
+http://47.96.69.138:7080/
+
+api接口文档地址:
+https://www.showdoc.com.cn/AQL666666/
+
+话费下单地址:
+http://47.96.69.138:9086/onlinepay.do
+订单主动查询地址:
+http://47.96.69.138:9086/searchpay.do
+余额查询:
+http://47.96.69.138:9086/searchbalance.do
+
+
+101687	全国移动话费30元直充
+101688	全国移动话费50元直充
+101689	全国移动话费100元直充
+101690	全国移动话费200元直充
+
+101705	全国联通话费30元直充
+101706	全国联通话费50元直充
+101707	全国联通话费100元直充
+101708	全国联通话费200元直充
+
+101723	全国电信话费30元直充
+101724	全国电信话费50元直充
+101725	全国电信话费100元直充
+101726	全国电信话费200元直充
+
+
+

+ 0 - 37
helper/refill/api/xyz/ruixunda/开户信息.txt

@@ -1,37 +0,0 @@
-后台地址:http://47.98.117.207:8888
-帐号:bjyz9825
-密码:430195
-appId:HopCzvajlL
-appSecret:iLDpqQtdzhOaaNms
-后台-商品列表,可查看已配置商品信息
-后台-安全中心,可配置IP白名单
-接口文档:https://www.showdoc.com.cn/1686453783298366/7925312871840290
-话费直充接口:http://47.98.117.207:8911/api/hf/order/submit
-通用直充接口:http://47.98.117.207:8911/api/order/submit
-卡密提取接口:http://47.98.117.207:8911/api/card/get
-查询接口接口:http://47.98.117.207:8911/api/order/query
-余额查询接口:http://47.98.117.207:8911/api/account/balance
-
-全国移动编码
-全国移动30   7
-全国移动50   8
-全国移动100   9
-全国移动200   10
-全国移动300   11
-全国移动500   12
-
-全国联通编码
-全国联通30  13
-全国联通50  14
-全国联通100  15
-全国联通200  16
-全国联通300  17
-全国联通500  18
-
-全国电信编码
-全国电信30  19
-全国电信50  20
-全国电信100  21
-全国电信200  22
-全国电信300  23
-全国电信500  24

+ 4 - 3
helper/refill/api/xyz/yelin_hf/RefillCallBack.php

@@ -59,17 +59,18 @@ class RefillCallBack implements refill\IRefillCallBack
             return [false, false, false,false];
         }
         $order_id = $order_info['order_id'];
-        Model('refill_order')->edit($order_id, ['ch_trade_no' => $params['trade_no']]);
         if ($status === 'SUCCESS') {
+            $data['ch_trade_no'] = $params['trade_no'];
             $data['official_sn'] = strtolower($params['official_sn']) == 'null' ? '' : $params['official_sn'];
             Model('refill_order')->edit($order_id, $data);
             return [$order_id, true, false,true];
         }
         elseif ($status === 'CANCEL') {
-            return [$order_id, false, false,true];
+            Model('refill_order')->edit($order_id, ['ch_trade_no' => $params['trade_no']]);
+            return [$order_id, false, true,true];
         }
         else {
             return [$order_id, false, false,false];
         }
     }
-}
+}

+ 3 - 2
helper/refill/api/xyz/yelin_hf/RefillPhone.php

@@ -73,12 +73,13 @@ class RefillPhone extends refill\IRefillPhone
             elseif ($resp['code'] === 200)
             {
                 $data = $resp['datas'];
-                Model('refill_order')->edit($refill_info['order_id'], ['ch_trade_no' => $data['trade_no']]);
                 if ($data['order_state'] == '40') {
+                    $save['ch_trade_no'] = $data['trade_no'];
                     $save['official_sn'] = strtolower($resp['official_sn']) == 'null' ? '' : $resp['official_sn'];
                     Model('refill_order')->edit($refill_info['order_id'], $save);
                     $order_state = ORDER_STATE_SUCCESS;
                 } elseif ($data['order_state'] === '0') {
+                    Model('refill_order')->edit($refill_info['order_id'], ['ch_trade_no' => $data['trade_no']]);
                     $order_state = ORDER_STATE_CANCEL;
                 } elseif (in_array($data['order_state'], ['10', '20', '30', '50'], true)) {
                     $order_state = ORDER_STATE_SEND;
@@ -151,4 +152,4 @@ class RefillPhone extends refill\IRefillPhone
 
         return md5($body);
     }
-}
+}

+ 50 - 0
helper/refill/api/yl/dazhanggui_high/RefillCallBack.php

@@ -0,0 +1,50 @@
+<?php
+namespace refill\dazhanggui_high;
+
+require_once(BASE_HELPER_RAPI_PATH . '/dazhanggui_high/config.php');
+
+use refill;
+class RefillCallBack implements refill\IRefillCallBack
+{
+    public function verify($params): bool
+    {
+        $sign = $this->sign($params);
+        if ($params['szVerifyString'] == $sign) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$userid}&szOrderId={$params['szOrderId']}&szPhoneNum={$params['szPhoneNum']}&nDemo={$params['nDemo']}&fSalePrice={$params['fSalePrice']}";
+        $content .= "&nFlag={$params['nFlag']}&szKey={$key}";
+        return md5($content);
+    }
+
+    public function notify($params)
+    {
+        $status = intval($params['nFlag']);
+        $order_sn = $params['szOrderId'];
+        $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false,false];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $data['official_sn'] = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false,true];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true,true];
+        }
+        else {
+            return [$order_id, false, false,false];
+        }
+    }
+}

+ 142 - 0
helper/refill/api/yl/dazhanggui_high/RefillPhone.php

@@ -0,0 +1,142 @@
+<?php
+
+namespace refill\dazhanggui_high;
+
+require_once(BASE_HELPER_RAPI_PATH . '/dazhanggui_high/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $phone, int $amount, int $card_type, string $order_sn)
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $params['szOrderId'] = $order_sn;
+        $params['szPhoneNum'] = $phone;
+        $params['nMoney'] = $amount;
+        $params['nSortType'] = config::operator[$card_type];
+        $params['szProductId'] = config::Product[$card_type][$amount];
+        $params['nProductClass'] = 1;
+        $params['nProductType'] = 1;
+        $params['szTimeStamp'] = date("Y-m-d H:i:s");
+        $params['szNotifyUrl'] = config::NOTIFY_URL;
+        return $params;
+    }
+
+    public function add($card_no, $card_type, $amount, $params,&$net_errno = 0)
+    {
+        $order_sn = $params['order_sn'];
+        $params = $this->req_params($card_no, $amount, $card_type, $order_sn);
+
+        $sign = $this->sign($params);
+        $params['szVerifyString'] = $sign;
+
+        $resp = http_request(config::ORDER_URL, $params, 'POST', false, config::ExtHeaders, $net_errno);
+
+        if (empty($resp)) {
+            return [false, '网络错误', true];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+
+            $nRtn = $resp['nRtn'];
+            if (empty($resp)) {
+                return [false, '网络错误', true];
+            } elseif ($nRtn === 0) {
+                return [true, '', false];
+            } elseif (in_array($nRtn, config::ERR_NOS, true)) {
+                return [false, $resp['szRtnCode'], false];
+            } elseif (in_array($nRtn, [2050, 999], true)) {
+                $net_errno = "HTTP-{$nRtn}";
+                return [false, $resp['szRtnCode'], true];
+            } else {
+                $err = 998;
+                $net_errno = "HTTP-{$err}";
+                return [false, $resp['szRtnCode'], true];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $params['szOrderId'] = $refill_info['order_sn'];
+        $key = config::KEY;
+        $content = "szAgentId={$params['szAgentId']}&szOrderId={$params['szOrderId']}&szKey={$key}";
+        $params['szVerifyString'] = md5($content);
+
+        $resp = http_request(config::QUERY_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            }
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $updata['official_sn'] = $resp['szRtnMsg'];
+                Model('refill_order')->edit($refill_info['order_id'], $updata);
+                $order_state = ORDER_STATE_SUCCESS;
+            } elseif ($status === 5013) {
+                $order_state = ORDER_STATE_CANCEL;
+            } elseif (in_array($status, [5011,5019],true)) {
+                $order_state = ORDER_STATE_SEND;
+            } elseif ($status === 5005 && (time() - $refill_info['commit_time'] >= 300)) {
+                $order_state = ORDER_STATE_NOEXIST;
+            } else {
+                return [false, $resp['szRtnMsg']];
+            }
+
+            return [true, $order_state];
+        }
+    }
+
+    public function balance()
+    {
+        $params['szAgentId'] = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$params['szAgentId']}&szKey={$key}";
+        $params['szVerifyString'] = md5($content);
+
+        $resp = http_request(config::BALANCE_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            } elseif ($resp['nRtn'] === 0) {
+                return [true, $resp['fBalance']];
+            } else {
+                return [false, $resp['szRtnCode']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "szAgentId={$userid}&szOrderId={$params['szOrderId']}&szPhoneNum={$params['szPhoneNum']}&nMoney={$params['nMoney']}&nSortType={$params['nSortType']}";
+        $content .= "&nProductClass={$params['nProductClass']}&nProductType={$params['nProductType']}&szTimeStamp={$params['szTimeStamp']}&szKey={$key}";
+        return md5($content);
+    }
+}

+ 15 - 0
helper/refill/api/yl/dazhanggui_high/api.txt

@@ -0,0 +1,15 @@
+登录账号:ylgj01
+登录密码:123456
+话费下单地址:http://47.101.136.81:10186/plat/api/old/submitorder
+查询地址:http://47.101.136.81:10186/plat/api/old/queryorder
+查询余额地址:http://47.101.136.81:10186/plat/api/old/queryBalance
+
+正式ID:	200022
+秘钥: d5ea1e8fce344caa8a6263427dbca611
+
+后台登录地址:http://47.101.136.81:10186/plat/index
+对接文档地址:https://docs.qq.com/doc/DWkV1VkxQVk13eEtQ
+
+全国移动50元	1000050
+全国移动100元	1000100
+全国移动200元	1000200

+ 35 - 0
helper/refill/api/yl/dazhanggui_high/config.php

@@ -0,0 +1,35 @@
+<?php
+
+
+namespace refill\dazhanggui_high;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://47.101.136.81:10186/plat/api/old/submitorder';
+    const QUERY_URL= 'http://47.101.136.81:10186/plat/api/old/queryorder';
+    const BALANCE_URL = 'http://47.101.136.81:10186/plat/api/old/queryBalance';
+
+    const USER_ID= '200022';
+    const KEY = 'd5ea1e8fce344caa8a6263427dbca611';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_dazhanggui_high.php";
+
+    const operator = [
+        mtopcard\ChinaMobileCard  => 1,
+        mtopcard\ChinaUnicomCard  => 2,
+        mtopcard\ChinaTelecomCard => 3
+    ];
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
+
+    const ERR_NOS = [
+        1000,1001,1003,1004,2001,2002,2003,2020,2021,1006,2030,3003
+    ];
+
+    const Product = [
+        mtopcard\ChinaMobileCard => [
+            50  => 1000050,
+            100 => 1000100,
+            200 => 1000200,
+        ]
+    ];
+}

+ 4 - 4
helper/refill/api/yl/guochuang/config.php

@@ -67,12 +67,12 @@ class config
         "4-10-6" => 9.825, "4-20-6" => 19.65, "4-30-6" => 29.475, "4-50-6" => 49.125, "4-100-6" => 98.25, "4-200-6" => 196.5, "4-300-6" => 294.75, "4-500-6" => 491.25,//辽宁 6
         "4-10-9" => 9.94, "4-20-9" => 19.88, "4-30-9" => 29.82, "4-50-9" => 49.7, "4-100-9" => 99.4,//上海 9
         "4-10-8" => 10.03, "4-20-8" => 20.06, "4-30-8" => 30.09, "4-50-8" => 50.15, "4-100-8" => 100.3, "4-200-8" => 200.6, "4-300-8" => 301.2, "4-500-8" => 502,//黑龙江 8
-        "4-10-29" => 9.815, "4-20-29" => 19.63, "4-30-29" => 29.445, "4-50-29" => 49.075, "4-100-29" => 98.15, "4-200-29" => 196.3, "4-300-29" => 294.45, "4-500-29" => 490.75,//青海 29
+        "4-10-29" => 9.86, "4-20-29" => 19.72, "4-30-29" => 29.58, "4-50-29" => 49.3, "4-100-29" => 98.6, "4-200-29" => 197.2, "4-300-29" => 295.8, "4-500-29" => 493,//青海 29
         "4-10-28" => 9.985, "4-20-28" => 19.97, "4-30-28" => 29.955, "4-50-28" => 49.925, "4-100-28" => 99.85, "4-200-28" => 199.7, "4-300-28" => 299.55, "4-500-28" => 499.25,//甘肃 28
         "4-10-13" => 10.22, "4-20-13" => 19.94, "4-30-13" => 29.91, "4-50-13" => 49.85, "4-100-13" => 99.7, "4-200-13" => 199.4, "4-300-13" => 300.9, "4-500-13" => 501.5,//福建 13
         "4-10-5" => 10.035, "4-20-5" => 20.07, "4-30-5" => 30.09, "4-50-5" => 50.15, "4-100-5" => 100.3, "4-200-5" => 200.4, "4-300-5" => 300.6, "4-500-5" => 501,//内蒙古 5
         "4-30-18" => 29.835, "4-50-18" => 49.725, "4-100-18" => 99.45, "4-200-18" => 198.3,//湖南 18
-        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.97, "4-50-19" => 49.95, "4-100-19" => 99.9, "4-200-19" => 199.8, "4-300-19" => 299.7, "4-500-19" => 499.5,//广东 19
+        "4-10-19" => 9.99, "4-20-19" => 19.98, "4-30-19" => 29.88, "4-50-19" => 49.8, "4-100-19" => 99.6, "4-200-19" => 199.2, "4-300-19" => 298.8, "4-500-19" => 498,//广东 19
         "4-10-7" => 9.93, "4-20-7" => 19.86, "4-30-7" => 29.52, "4-50-7" => 49.2, "4-100-7" => 98.4, "4-200-7" => 196.8, "4-300-7" => 295.2, "4-500-7" => 492,//吉林 7
         "4-10-1" => 10.31, "4-20-1" => 20.32, "4-30-1" => 30.33, "4-50-1" => 50.35, "4-100-1" => 100.4, "4-200-1" => 200.3, "4-300-1" => 300.45, "4-500-1" => 500.75,//北京 1
         "4-10-22" => 10.015, "4-20-22" => 20.03, "4-30-22" => 30.045, "4-50-22" => 50.075, "4-100-22" => 100.15, "4-200-22" => 200.3, "4-300-22" => 300.45, "4-500-22" => 500.75,//重庆 22
@@ -81,7 +81,7 @@ class config
         "4-10-11" => 9.945, "4-20-11" => 19.89, "4-30-11" => 29.835, "4-50-11" => 49.725, "4-100-11" => 99.45, "4-200-11" => 198.9, "4-300-11" => 298.35, "4-500-11" => 497.25,//浙江 11
         "4-10-17" => 9.945, "4-20-17" => 19.89, "4-30-17" => 29.835, "4-50-17" => 49.725, "4-100-17" => 99.45, "4-200-17" => 198.9, "4-300-17" => 298.35, "4-500-17" => 497.25,//湖北 17
         "4-10-16" => 10.24, "4-20-16" => 20.28, "4-30-16" => 30.3, "4-50-16" => 50.35, "4-100-16" => 100.4, "4-200-16" => 200.8, "4-300-16" => 301.2, "4-500-16" => 502,//河南 16
-        "4-50-4" => 49.75, "4-100-4" => 99.5, "4-200-4" => 199,//山西 4
+        "4-10-4" => 10.3, "4-20-4" => 20.6, "4-30-4" => 30.9, "4-50-4" => 50.1, "4-100-4" => 100.2, "4-200-4" => 200.4, "4-300-4" => 300.6, "4-500-4" => 501,//山西 4
         "4-10-24" => 10.18, "4-20-24" => 20.18, "4-30-24" => 30.21, "4-50-24" => 50.1, "4-100-24" => 100.2, "4-200-24" => 200.4, "4-300-24" => 300.6, "4-500-24" => 501,//贵州 24
         "4-10-30" => 10.12, "4-20-30" => 20.24, "4-30-30" => 30.129, "4-50-30" => 50.15, "4-100-30" => 100.2, "4-200-30" => 200.4, "4-300-30" => 300.3, "4-500-30" => 500.5,//宁夏 30
         "4-10-25" => 10.14, "4-20-25" => 20.2, "4-30-25" => 30.18, "4-50-25" => 50.1, "4-100-25" => 100.2, "4-200-25" => 200.4, "4-300-25" => 300.6, "4-500-25" => 501,//云南 25
@@ -99,4 +99,4 @@ class config
         "6-10-15" => 10.21, "6-20-15" => 20.22, "6-30-15" => 30.231, "6-50-15" => 50.25, "6-100-15" => 100.3, "6-200-15" => 200.3, "6-300-15" => 300.45, "6-500-15" => 500.75,//山东 15
         "6-10-12" => 10.04, "6-20-12" => 20.05, "6-30-12" => 30.12, "6-50-12" => 50.2, "6-100-12" => 100.4, "6-200-12" => 200.6, "6-300-12" => 300.9, "6-500-12" => 501.5,//安徽 12
     ];
-}
+}

+ 11 - 30
helper/refill/api/yl/ruixunda/RefillCallBack.php

@@ -8,9 +8,7 @@ class RefillCallBack implements refill\IRefillCallBack
 {
     public function verify($params): bool
     {
-        $input = $params;
-        unset($input['sign']);
-        $sign = $this->sign($input);
+        $sign = $this->sign($params);
         if ($params['sign'] == $sign) {
             return true;
         } else {
@@ -20,45 +18,28 @@ class RefillCallBack implements refill\IRefillCallBack
 
     private function sign($params)
     {
-        $params['appSecret'] = config::APP_SECRET;
-        ksort($params);
-        $content = '';
-        foreach ($params as $key => $value) {
-            if($this->check_empty($value) === false) {
-                $content .= "{$key}={$value}&";
-            }
-        }
-        $content = rtrim($content, '&');
-        return md5($content);
-    }
-
-    private function check_empty($value)
-    {
-        if (!isset($value))
-            return true;
-        if ($value === null)
-            return true;
-        if (trim($value) === "")
-            return true;
-
-        return false;
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&orderid={$params['orderid']}&sporderid={$params['sporderid']}&merchantsubmittime={$params['merchantsubmittime']}";
+        $content .= "&resultno={$params['resultno']}&key={$key}";
+        return strtoupper(md5($content));
     }
 
     public function notify($params)
     {
-        $status = intval($params['orderStatus']);
-        $order_sn = $params['outOrderId'];
+        $status = intval($params['resultno']);
+        $order_sn = $params['sporderid'];
         $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
         if (empty($order_info)) {
             return [false, false, false,false];
         }
 
         $order_id = $order_info['order_id'];
-        if ($status === 2) {
-            $data['official_sn'] = strtolower($params['ext1']) == 'null' ? '' : $params['ext1'];
+        if ($status === 1) {
+            $data['official_sn'] = strtolower($params['remark1']) == 'null' ? '' : $params['remark1'];
             Model('refill_order')->edit($order_id, $data);
             return [$order_id, true, false, true];
-        } elseif ($status === 3) {
+        } elseif ($status === 9) {
             return [$order_id, false, true, true];
         } else {
             return [$order_id, false, false, false];

+ 62 - 62
helper/refill/api/yl/ruixunda/RefillPhone.php

@@ -14,15 +14,18 @@ class RefillPhone extends refill\IRefillPhone
         parent::__construct($cfgs);
     }
 
-    private function req_params(int $phone, int $amount, int $card_type, string $order_sn)
+    private function req_params(int $phone, int $amount, $card_type, string $order_sn)
     {
-        $params['appId'] = config::APP_ID;
-        $params['outOrderId'] = $order_sn;
-        $params['uuid'] = $phone;
-        $params['itemId'] = config::PRODUCT[$card_type][$amount];
-        $params['itemFace'] = $amount;
-        $params['callbackUrl'] = config::NOTIFY_URL;
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
+        $params['userid'] = config::USER_ID;
+        $params['productid'] = config::ProductIdS[$card_type][$amount];
+        $params['price'] = $amount;
+        $params['num'] = 1;
+        $params['mobile'] = $phone;
+        $params['spordertime'] = date("YmdHis");
+        $params['sporderid'] = $order_sn;
+        $params['back_url'] = config::NOTIFY_URL;
+        $params['paytype'] = config::operator[$card_type];
+
         return $params;
     }
 
@@ -30,9 +33,7 @@ class RefillPhone extends refill\IRefillPhone
     {
         $order_sn = $params['order_sn'];
         $params = $this->req_params($card_no, $amount, $card_type, $order_sn);
-        if(empty($params['itemId'])) {
-            return [false, '商品编号错误', false];
-        }
+
         $sign = $this->sign($params);
         $params['sign'] = $sign;
 
@@ -44,29 +45,35 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
+            $resp = $this->xmlToArray($resp);
             if (empty($resp)) {
                 return [false, '网络错误', true];
-            } elseif ($resp['code'] === '00') {
-                return [true, $resp['orderId'], false];
-            } elseif (in_array($resp['code'], config::ERRCODES, true)) {
-                return [false, $resp['msg'], false];
-            } elseif (in_array($resp['code'], ['-22', '-23', '-99'], true)) {
-                $net_errno = "HTTP-{$resp['code']}";
-                return [false, $resp['msg'], true];
+            }
+
+            $resultno = $resp['resultno'];
+            if (in_array($resultno, ['0', '2'], true)) {
+                return [true, $resp['orderid'], false];
+            } elseif (in_array($resultno, config::ERR_NOS, true)) {
+                return [false, $resultno, false];
+            } elseif ($resultno === '9999' || $resultno === '5006') {
+                $net_errno = "HTTP-{$resultno}";
+                return [false, $resultno, true];
             } else {
-                $net_errno = "HTTP-998";
-                return [false, $resp['msg'], true];
+                //未知结果码
+                $err = 998;
+                $net_errno = "HTTP-{$err}";
+                return [false, $resultno, true];
             }
         }
     }
 
     public function query($refill_info)
     {
-        $params['appId'] = config::APP_ID;
-        $params['outOrderId'] = $refill_info['order_sn'];
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
-        $params['sign'] = $this->sign($params);
+        $params['userid'] = config::USER_ID;
+        $params['sporderid'] = $refill_info['order_sn'];
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&sporderid={$params['sporderid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
 
         $resp = http_request(config::QUERY_URL, $params, 'POST', false, config::ExtHeaders);
 
@@ -76,40 +83,39 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
-            if (empty($resp)) {
+            $resp = $this->xmlToArray($resp);
+            if (empty($resp))
+            {
                 return [false, '网络错误'];
             }
-            elseif ($resp['code'] === '00')
+            else
             {
-                $status = $resp['orderStatus'];
-                if ($status === '2') {
-                    $updata['official_sn'] = $resp['ext1'];
+                $resultno = $resp['resultno'];
+                if ($resultno === '1') {
+                    $updata['official_sn'] = $resp['remark1'];
                     Model('refill_order')->edit($refill_info['order_id'], $updata);
                     $order_state = ORDER_STATE_SUCCESS;
-                } elseif ($status === '3') {
+                } elseif ($resultno === '9') {
                     $order_state = ORDER_STATE_CANCEL;
-                } elseif ($status === '1') {
+                } elseif (in_array($resultno, ['0','2'], true)) {
                     $order_state = ORDER_STATE_SEND;
-                } elseif ($status === '4' && (time() - $refill_info['commit_time'] >= 600)) {
+                } elseif ($resultno === '5007' && (time() - $refill_info['commit_time'] > 600)) {
                     $order_state = ORDER_STATE_NOEXIST;
                 } else {
-                    return [false, $resp['msg']];
+                    return [false, $resultno];
                 }
+
                 return [true, $order_state];
             }
-            else
-            {
-                return [false, $resp['msg']];
-            }
         }
     }
 
     public function balance()
     {
-        $params['appId'] = config::APP_ID;
-        $params['timestamp'] = date("YmdHis").$this->get_millisecond();
-        $params['sign'] = $this->sign($params);
+        $params['userid'] = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
 
         $resp = http_request(config::BALANCE_URL, $params, 'POST', false, config::ExtHeaders);
 
@@ -119,37 +125,31 @@ class RefillPhone extends refill\IRefillPhone
         else
         {
             Log::record($resp, Log::DEBUG);
-            $resp = json_decode($resp, true);
+            $resp = $this->xmlToArray($resp);
             if (empty($resp)) {
                 return [false, '网络错误'];
-            } elseif ($resp['code'] === '00') {
+            } elseif ($resp['resultno'] === '1') {
                 return [true, $resp['balance']];
             } else {
-                return [false, $resp['msg']];
+                return [false, $resp['resultno']];
             }
         }
     }
 
-    /**
-     * 获取毫秒级别的时间戳
-     */
-    private function get_millisecond()
+    private function sign($params)
     {
-        list($usec, $sec) = explode(" ", microtime());
-        return round($usec*1000);
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&productid={$params['productid']}&price={$params['price']}&num={$params['num']}&mobile={$params['mobile']}&spordertime={$params['spordertime']}";
+        $content .= "&sporderid={$params['sporderid']}&key={$key}";
+        return strtoupper(md5($content));
     }
 
-    private function sign($params)
+    public function xmlToArray($xml)
     {
-        $params['appSecret'] = config::APP_SECRET;
-        ksort($params);
-        $content = '';
-        foreach ($params as $key => $value) {
-            if($this->check_empty($value) === false) {
-                $content .= "{$key}={$value}&";
-            }
-        }
-        $content = rtrim($content, '&');
-        return md5($content);
+        $replace_str = str_replace(' ','','encoding="gb2312"');
+        $xml = mb_convert_encoding($xml,"UTF-8","gb2312");
+        $xml = str_replace($replace_str, "encoding='utf-8'", $xml);
+        return refill\util::xmlToArray($xml);
     }
 }

+ 38 - 32
helper/refill/api/yl/ruixunda/config.php

@@ -6,39 +6,45 @@ namespace refill\ruixunda;
 use mtopcard;
 class config
 {
-    const ORDER_URL = 'http://47.98.117.207:8911/api/hf/order/submit';
-    const QUERY_URL = 'http://47.98.117.207:8911/api/order/query';
-    const BALANCE_URL = 'http://47.98.117.207:8911/api/account/balance';
+    //https://www.showdoc.com.cn/AQL666666/
+    const ORDER_URL = 'http://47.96.69.138:9086/onlinepay.do';
+    const QUERY_URL= 'http://47.96.69.138:9086/searchpay.do';
+    const BALANCE_URL = 'http://47.96.69.138:9086/searchbalance.do';
 
-    const APP_ID = 'G0sEOnF3jm';
-    const APP_SECRET = 'bbpZLlMcJChpNFgn';
+    const USER_ID= '10002505';
+    const KEY = 'k2xkSaFr4BH5ZD5iDWf5Ha4QTE3fKtN5';
     const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_ruixunda.php";
-    const PRODUCT = [
-        mtopcard\ChinaMobileCard => [
-            30  => 7,
-            50  => 8,
-            100 => 9,
-            200 => 10,
-            300 => 11,
-            500 => 12,
-        ],
-        mtopcard\ChinaUnicomCard => [
-            30  => 13,
-            50  => 14,
-            100 => 15,
-            200 => 16,
-            300 => 17,
-            500 => 18,
-        ],
-        mtopcard\ChinaTelecomCard => [
-            30  => 19,
-            50  => 20,
-            100 => 21,
-            200 => 22,
-            300 => 23,
-            500 => 24,
-        ],
+
+    const operator = [
+        mtopcard\ChinaMobileCard  => 'yd',
+        mtopcard\ChinaUnicomCard  => 'lt',
+        mtopcard\ChinaTelecomCard => 'dx'
+    ];
+    const ERR_NOS = [
+        '5001','5002','5003','5004','5005','5008','5009','5010','5011','5012'
+    ];
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;'];
+    const ProductIdS = [
+        mtopcard\ChinaMobileCard =>
+            [
+                30  => '101687',
+                50  => '101688',
+                100 => '101689',
+                200 => '101690',
+            ],
+        mtopcard\ChinaUnicomCard =>
+            [
+                30  => '101705',
+                50  => '101706',
+                100 => '101707',
+                200 => '101708',
+            ],
+        mtopcard\ChinaTelecomCard =>
+            [
+                30  => '101723',
+                50  => '101724',
+                100 => '101725',
+                200 => '101726',
+            ]
     ];
-    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
-    const ERRCODES = ['-10', '-12', '-13', '-14', '-15', '-16', '-18', '-21'];
 }

BIN
helper/refill/api/yl/ruixunda/云九一商品编码.docx


+ 35 - 0
helper/refill/api/yl/ruixunda/对接文档-yezi.txt

@@ -0,0 +1,35 @@
+登录名:椰林全国
+密码:yelin8765
+用户编码:10002505
+密钥:k2xkSaFr4BH5ZD5iDWf5Ha4QTE3fKtN5
+
+
+下游客户注册和登录地址:
+http://47.96.69.138:7080/
+
+api接口文档地址:
+https://www.showdoc.com.cn/AQL666666/
+
+话费下单地址:
+http://47.96.69.138:9086/onlinepay.do
+订单主动查询地址:
+http://47.96.69.138:9086/searchpay.do
+余额查询:
+http://47.96.69.138:9086/searchbalance.do
+
+
+101687	全国移动话费30元直充
+101688	全国移动话费50元直充
+101689	全国移动话费100元直充
+101690	全国移动话费200元直充
+
+101723	全国电信话费30元直充
+101724	全国电信话费50元直充
+101725	全国电信话费100元直充
+101726	全国电信话费200元直充
+
+101705	全国联通话费30元直充
+101706	全国联通话费50元直充
+101707	全国联通话费100元直充
+101708	全国联通话费200元直充
+

+ 0 - 37
helper/refill/api/yl/ruixunda/开户信息.txt

@@ -1,37 +0,0 @@
-后台地址:http://47.98.117.207:8888
-帐号:yelin7639
-密码:386751
-appId:G0sEOnF3jm
-appSecret:bbpZLlMcJChpNFgn
-后台-商品列表,可查看已配置商品信息
-后台-安全中心,可配置IP白名单
-接口文档:https://www.showdoc.com.cn/1686453783298366/7925312871840290
-话费直充接口:http://47.98.117.207:8911/api/hf/order/submit
-通用直充接口:http://47.98.117.207:8911/api/order/submit
-卡密提取接口:http://47.98.117.207:8911/api/card/get
-查询接口接口:http://47.98.117.207:8911/api/order/query
-余额查询接口:http://47.98.117.207:8911/api/account/balance
-
-全国移动编码
-全国移动30   7
-全国移动50   8
-全国移动100   9
-全国移动200   10
-全国移动300   11
-全国移动500   12
-
-全国联通编码
-全国联通30  13
-全国联通50  14
-全国联通100  15
-全国联通200  16
-全国联通300  17
-全国联通500  18
-
-全国电信编码
-全国电信30  19
-全国电信50  20
-全国电信100  21
-全国电信200  22
-全国电信300  23
-全国电信500  24

+ 48 - 0
helper/refill/api/yl/weixue/RefillCallBack.php

@@ -0,0 +1,48 @@
+<?php
+namespace refill\weixue;
+
+require_once(BASE_HELPER_RAPI_PATH . '/weixue/config.php');
+
+use refill;
+class RefillCallBack implements refill\IRefillCallBack
+{
+    public function verify($params): bool
+    {
+        $sign = $this->sign($params);
+        if ($params['sign'] == $sign) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&orderid={$params['orderid']}&sporderid={$params['sporderid']}&merchantsubmittime={$params['merchantsubmittime']}";
+        $content .= "&resultno={$params['resultno']}&key={$key}";
+        return strtoupper(md5($content));
+    }
+
+    public function notify($params)
+    {
+        $status = intval($params['resultno']);
+        $order_sn = $params['sporderid'];
+        $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false,false];
+        }
+
+        $order_id = $order_info['order_id'];
+        if ($status === 1) {
+            $data['official_sn'] = strtolower($params['remark1']) == 'null' ? '' : $params['remark1'];
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true];
+        } elseif ($status === 9) {
+            return [$order_id, false, true, true];
+        } else {
+            return [$order_id, false, false, false];
+        }
+    }
+}

+ 155 - 0
helper/refill/api/yl/weixue/RefillPhone.php

@@ -0,0 +1,155 @@
+<?php
+
+namespace refill\weixue;
+
+require_once(BASE_HELPER_RAPI_PATH . '/weixue/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $phone, int $amount, $card_type, string $order_sn)
+    {
+        $params['userid'] = config::USER_ID;
+        $params['productid'] = config::ProductIdS[$card_type][$amount];
+        $params['price'] = $amount;
+        $params['num'] = 1;
+        $params['mobile'] = $phone;
+        $params['spordertime'] = date("YmdHis");
+        $params['sporderid'] = $order_sn;
+        $params['back_url'] = config::NOTIFY_URL;
+        $params['paytype'] = config::operator[$card_type];
+
+        return $params;
+    }
+
+    public function add($card_no, $card_type, $amount, $params,&$net_errno = 0)
+    {
+        $order_sn = $params['order_sn'];
+        $params = $this->req_params($card_no, $amount, $card_type, $order_sn);
+
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::ORDER_URL, $params, 'POST', false, config::ExtHeaders, $net_errno);
+
+        if (empty($resp)) {
+            return [false, '网络错误', true];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = $this->xmlToArray($resp);
+            if (empty($resp)) {
+                return [false, '网络错误', true];
+            }
+
+            $resultno = $resp['resultno'];
+            if (in_array($resultno, ['0', '2'], true)) {
+                return [true, $resp['orderid'], false];
+            } elseif (in_array($resultno, config::ERR_NOS, true)) {
+                return [false, $resultno, false];
+            } elseif ($resultno === '9999' || $resultno === '5006') {
+                $net_errno = "HTTP-{$resultno}";
+                return [false, $resultno, true];
+            } else {
+                //未知结果码
+                $err = 998;
+                $net_errno = "HTTP-{$err}";
+                return [false, $resultno, true];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['userid'] = config::USER_ID;
+        $params['sporderid'] = $refill_info['order_sn'];
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&sporderid={$params['sporderid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
+
+        $resp = http_request(config::QUERY_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = $this->xmlToArray($resp);
+            if (empty($resp))
+            {
+                return [false, '网络错误'];
+            }
+            else
+            {
+                $resultno = $resp['resultno'];
+                if ($resultno === '1') {
+                    $updata['official_sn'] = $resp['remark1'];
+                    Model('refill_order')->edit($refill_info['order_id'], $updata);
+                    $order_state = ORDER_STATE_SUCCESS;
+                } elseif ($resultno === '9') {
+                    $order_state = ORDER_STATE_CANCEL;
+                } elseif (in_array($resultno, ['0','2'], true)) {
+                    $order_state = ORDER_STATE_SEND;
+                } elseif ($resultno === '5007' && (time() - $refill_info['commit_time'] > 600)) {
+                    $order_state = ORDER_STATE_NOEXIST;
+                } else {
+                    return [false, $resultno];
+                }
+
+                return [true, $order_state];
+            }
+        }
+    }
+
+    public function balance()
+    {
+        $params['userid'] = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$params['userid']}&key={$key}";
+        $params['sign'] = strtoupper(md5($content));
+
+        $resp = http_request(config::BALANCE_URL, $params, 'POST', false, config::ExtHeaders);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = $this->xmlToArray($resp);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            } elseif ($resp['resultno'] === '1') {
+                return [true, $resp['balance']];
+            } else {
+                return [false, $resp['resultno']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        $userid = config::USER_ID;
+        $key = config::KEY;
+        $content = "userid={$userid}&productid={$params['productid']}&price={$params['price']}&num={$params['num']}&mobile={$params['mobile']}&spordertime={$params['spordertime']}";
+        $content .= "&sporderid={$params['sporderid']}&key={$key}";
+        return strtoupper(md5($content));
+    }
+
+    public function xmlToArray($xml)
+    {
+        $replace_str = str_replace(' ','','encoding="gb2312"');
+        $xml = mb_convert_encoding($xml,"UTF-8","gb2312");
+        $xml = str_replace($replace_str, "encoding='utf-8'", $xml);
+        return refill\util::xmlToArray($xml);
+    }
+}

+ 44 - 0
helper/refill/api/yl/weixue/config.php

@@ -0,0 +1,44 @@
+<?php
+
+
+namespace refill\weixue;
+
+use mtopcard;
+class config
+{
+    //https://www.showdoc.com.cn/AQL666666/
+    const ORDER_URL = 'http://121.36.216.15:9086/onlinepay.do';
+    const QUERY_URL= 'http://121.36.216.15:9086/searchpay.do';
+    const BALANCE_URL = 'http://121.36.216.15:9086/searchbalance.do';
+
+    const USER_ID= '10002723';
+    const KEY = 'CpbwtEEGWGQWjtRGkGmRJjzQ4ZNErnch';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_weixue.php";
+
+
+    const operator = [
+        mtopcard\ChinaMobileCard  => 'yd',
+        mtopcard\ChinaUnicomCard  => 'lt',
+        mtopcard\ChinaTelecomCard => 'dx'
+    ];
+    const ERR_NOS = [
+        '5001','5002','5003','5004','5005','5008','5009','5010','5011','5012'
+    ];
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;'];
+    const ProductIdS = [
+        mtopcard\ChinaMobileCard =>
+            [
+                30  => '101687',
+                50  => '101688',
+                100 => '101689',
+                200 => '101690',
+            ],
+        mtopcard\ChinaUnicomCard =>
+            [
+                30  => '101705',
+                50  => '101706',
+                100 => '101707',
+                200 => '101708',
+            ],
+    ];
+}

+ 29 - 0
helper/refill/api/yl/weixue/对接文档-yezi.txt

@@ -0,0 +1,29 @@
+下游客户注册和登录地址:
+http://121.36.216.15:7080/
+
+api接口文档地址:
+https://www.showdoc.com.cn/AQL666666/
+
+下单地址:
+http://121.36.216.15:9086/onlinepay.do
+余额查询:
+http://121.36.216.15:9086/searchbalance.do
+订单主动查询地址:
+http://121.36.216.15:9086/searchpay.do
+
+ID:10002723
+秘钥:CpbwtEEGWGQWjtRGkGmRJjzQ4ZNErnch
+授信:30w
+密码:123456
+用户名:椰林
+
+
+101687 全国移动话费30元直充
+101688 全国移动话费50元直充
+101689 全国移动话费100元直充
+101690 全国移动话费200元直充
+
+101705 全国联通话费30元直充
+101706 全国联通话费50元直充
+101707 全国联通话费100元直充
+101708 全国联通话费200元直充

+ 76 - 0
helper/refill/api/yl/yezi_hf/RefillCallBack.php

@@ -0,0 +1,76 @@
+<?php
+namespace refill\yezi_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yezi_hf/config.php');
+use refill;
+class RefillCallBack implements refill\IRefillCallBack
+{
+    public function verify($params): bool
+    {
+        $input = $params;
+        unset($input['sign']);
+        $sign = $this->sign($input);
+        if ($params['sign'] == $sign) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected function check_empty($value)
+    {
+        if (!isset($value))
+            return true;
+        if ($value === null)
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    private function sign($params)
+    {
+        ksort($params);
+
+        $body = "";
+        $i = 0;
+        foreach ($params as $k => $v) {
+            if (false === $this->check_empty($v) && "@" != substr($v, 0, 1)) {
+                if ($i == 0) {
+                    $body .= "{$k}" . "=" . urlencode($v);
+                } else {
+                    $body .= "&" . "{$k}" . "=" . urlencode($v);
+                }
+                $i++;
+            }
+        }
+
+        $body .= "&key=".config::KEY;
+        return md5($body);
+    }
+
+    public function notify($params)
+    {
+        $status = $params['state'];
+        $order_sn = $params['order_sn'];
+        $order_info = Model('vr_order')->getOrderInfo(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false,false];
+        }
+        $order_id = $order_info['order_id'];
+        if ($status === 'SUCCESS') {
+            $data['ch_trade_no'] = $params['trade_no'];
+            $data['official_sn'] = strtolower($params['official_sn']) == 'null' ? '' : $params['official_sn'];
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false,true];
+        }
+        elseif ($status === 'CANCEL') {
+            Model('refill_order')->edit($order_id, ['ch_trade_no' => $params['trade_no']]);
+            return [$order_id, false, true,true];
+        }
+        else {
+            return [$order_id, false, false,false];
+        }
+    }
+}

+ 155 - 0
helper/refill/api/yl/yezi_hf/RefillPhone.php

@@ -0,0 +1,155 @@
+<?php
+
+namespace refill\yezi_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yezi_hf/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $phone, int $amount, string $order_sn)
+    {
+        $params['act'] = 'refill';
+        $params['op'] = 'add';
+        $params['mchid'] = config::MCH_ID;
+        $params['cardno'] = $phone;
+        $params['amount'] = $amount;
+        $params['order_sn'] = $order_sn;
+        $params['notifyurl'] = config::NOTIFY_URL;
+        return $params;
+    }
+
+    public function add($card_no, $card_type, $amount, $params,&$net_errno = 0)
+    {
+        $params = $this->req_params($card_no, $amount, $params['order_sn']);
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::ORDER_URL, $params , 'POST' , false , [] , $net_errno);
+
+        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'] === 200) {
+                return [true, '', false];
+            } else {
+                return [false, $resp['message'], false];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['act'] = 'refill';
+        $params['op'] = 'query';
+        $params['mchid'] = config::MCH_ID;
+        $params['order_sn'] = $refill_info['order_sn'];
+        $params['sign'] = $this->sign($params);
+
+        $resp = http_request(config::ORDER_URL, $params , 'POST');
+        if (empty($resp)) {
+            return [false, '系统错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '系统错误'];
+            }
+            elseif ($resp['code'] === 200)
+            {
+                $data = $resp['datas'];
+                if ($data['order_state'] == '40') {
+                    $save['ch_trade_no'] = $data['trade_no'];
+                    $save['official_sn'] = strtolower($resp['official_sn']) == 'null' ? '' : $resp['official_sn'];
+                    Model('refill_order')->edit($refill_info['order_id'], $save);
+                    $order_state = ORDER_STATE_SUCCESS;
+                } elseif ($data['order_state'] === '0') {
+                    Model('refill_order')->edit($refill_info['order_id'], ['ch_trade_no' => $data['trade_no']]);
+                    $order_state = ORDER_STATE_CANCEL;
+                } elseif (in_array($data['order_state'], ['10', '20', '30', '50'], true)) {
+                    $order_state = ORDER_STATE_SEND;
+                } else {
+                    return [false, $resp['message']];
+                }
+                return [true, $order_state];
+            } else {
+                return [false, $resp['message']];
+            }
+        }
+    }
+
+    public function balance()
+    {
+        $params['act'] = 'refill';
+        $params['op'] = 'balance';
+        $params['mchid'] = config::MCH_ID;
+        $params['sign'] = $this->sign($params);
+
+        $resp = http_request(config::ORDER_URL, $params , 'POST');
+
+        if (empty($resp)) {
+            return [false, '系统错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '系统错误'];
+            } elseif ($resp['code'] === 200) {
+                return [true, $resp['datas']['balance']];
+            } else {
+                return [false, $resp['message']];
+            }
+        }
+    }
+
+    protected function check_empty($value)
+    {
+        if (!isset($value))
+            return true;
+        if ($value === null)
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    private function sign($params)
+    {
+        ksort($params);
+
+        $body = "";
+        $i = 0;
+        foreach ($params as $k => $v) {
+            if (false === $this->check_empty($v) && "@" != substr($v, 0, 1)) {
+                if ($i == 0) {
+                    $body .= "{$k}" . "=" . urlencode($v);
+                } else {
+                    $body .= "&" . "{$k}" . "=" . urlencode($v);
+                }
+                $i++;
+            }
+        }
+
+        $body .= "&key=".config::KEY;
+
+        return md5($body);
+    }
+}

+ 7 - 0
helper/refill/api/yl/yezi_hf/api.txt

@@ -0,0 +1,7 @@
+https://admin.xyzshops.cn/merchant/#/login
+
+yelinyypc
+yls2308
+
+10310
+c5076f65f2ec370f4f331047811917dc

+ 13 - 0
helper/refill/api/yl/yezi_hf/config.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace refill\yezi_hf;
+
+class config
+{
+    const ORDER_URL = 'https://www.xyzshops.cn/mobile/index.php';
+
+    const MCH_ID = 10310;
+    const KEY = 'c5076f65f2ec370f4f331047811917dc';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_yezi_hf.php";
+
+}

+ 141 - 0
helper/refill/ops/pdlog_clear_refill.php

@@ -0,0 +1,141 @@
+<?php
+
+namespace refill;
+use Log;
+use trans_wapper;
+use Exception;
+
+class pdlog_clear_all
+{
+    const pdlog_table_name = 'pd_log';
+    const step_length = 1000;
+
+    public function clear($latest)
+    {
+        $lgid_getter = function ()
+        {
+            $item = Model()->table(self::pdlog_table_name)->field('min(lg_id) as minid,max(lg_id) as maxid')->find();
+            if(empty($item)) {
+                return [false,0,0];
+            }
+            else {
+                return [true,intval($item['minid']),intval($item['maxid'])];
+            }
+        };
+
+        [$succ,$minid,$maxid] = $lgid_getter();
+        if($latest > $minid) {
+            $minid = $latest;
+        }
+
+        if($succ) {
+            $this->delete_log($minid,$maxid);
+        }
+        return true;
+    }
+
+    private function delete_log($minid,$maxid)
+    {
+        $pd_log = Model();
+
+        /// 一批一批的删除日志
+        $batch_finder = function ($start, $end)
+        {
+            if($start > $end) return;
+
+            $quit = false;
+            while (!$quit)
+            {
+                $flag =  $start + self::step_length > $end ? $end : $start + self::step_length;
+                $cond = ['lg_id' => [['egt', $start], ['elt',$flag], 'and']];
+
+                $items = Model()->table(self::pdlog_table_name)
+                    ->field('*')
+                    ->where($cond)
+                    ->order('lg_id asc')->select();
+
+                if(!empty($items)) {
+                    yield $items;
+                }
+
+                if($flag >= $end) {
+                    break;
+                }
+                else {
+                    $start = $flag;
+                }
+            }
+        };
+
+        //return:1,可以直接删除,不需要存储; 2,不可以删除,3,检查后可以删除
+        $batch_check_log = function ($log)
+        {
+            $logid = intval($log['lg_id']);
+            $order_sn = $log['lg_order_sn'];
+            $lgtype = $log['lg_type'];
+
+            if (in_array($lgtype, ['bonus_add_money', 'hand_out_bonus', 'bonus_refund', 'bonus_expire'])) {
+                return [1, $logid];
+            }
+
+            if (empty($order_sn) && strlen($order_sn) < 20) {
+                return [2, false];
+            }
+
+            if (in_array($lgtype, ['order_pay', 'order_freeze', 'order_cancel'])) {
+                return [1, $logid];
+            }
+
+            return [2, $logid];
+        };
+
+        $batch_checker = function ($logs) use ($batch_check_log)
+        {
+            $del_ids = [];
+            foreach ($logs as $log)
+            {
+                [$type,$logid] = $batch_check_log($log);
+                if($type === 1) {
+                    $del_ids[] = $logid;
+                }
+            }
+
+            return $del_ids;
+        };
+
+        $batch_delter = function ($logids) use ($pd_log)
+        {
+            if (!empty($logids)) {
+                $result = $pd_log->table(self::pdlog_table_name)->where(['lg_id' => ['in',$logids]])->delete();
+                return $result;
+            } else {
+                return false;
+            }
+        };
+
+        $batch_handler = function ($minid, $maxid) use($batch_finder,$batch_checker,$batch_delter)
+        {
+            $index = 0;
+            $count = 0;
+            $batch_logs = $batch_finder($minid,$maxid);
+            foreach ($batch_logs as $logs)
+            {
+                $logids = $batch_checker($logs);
+                if(!empty($logids)) {
+                    $batch_delter($logids);
+                    $count += count($logids);
+                    Log::record("del pd_log lines={$count}",Log::DEBUG);
+
+//                    $index += 1;
+//                    if($index % 1000 === 0) {
+//                        Log::record("del pd_log index={$index}",Log::DEBUG);
+//                        sleep(1);
+//                    }
+                }
+            }
+        };
+
+        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+        $batch_handler($minid, $maxid);
+    }
+}

+ 1 - 1
helper/refill/policy/ctl_itemex.php

@@ -4,7 +4,7 @@ namespace refill;
 
 class ctl_itemex
 {
-    const feed_threshold = 10;
+    const feed_threshold = 2;
 
     private $mName;
     private $mCardType;

+ 4 - 4
helper/refill/policy/quaility.php

@@ -356,10 +356,10 @@ class Quality
             $cur_qualities = $all_qualities;
         }
 
-        if ($match_ratio) {
-            $all = $this->qualities($org_quality);
-            $cur_qualities = PolicyUtil::mixed_remove_last($org_quality, $cur_qualities, $all);
-        }
+//        if ($match_ratio) {
+//            $all = $this->qualities($org_quality);
+//            $cur_qualities = PolicyUtil::mixed_remove_last($org_quality, $cur_qualities, $all);
+//        }
 
         return [$cur_qualities,$match_ratio];
 

+ 4 - 0
mobile/callback/refill_dazhanggui_high.php

@@ -0,0 +1,4 @@
+<?php
+
+refill\util::push_notify('dazhanggui_high',$_POST);
+echo ('ok');

+ 1 - 1
mobile/callback/refill_ruixunda.php

@@ -1,4 +1,4 @@
 <?php
 
 refill\util::push_notify('ruixunda',$_POST);
-echo ('ok');
+echo ('OK');

+ 4 - 0
mobile/callback/refill_yezi_hf.php

@@ -0,0 +1,4 @@
+<?php
+
+refill\util::push_notify('yezi_hf',$_POST);
+echo ('SUCCESS');

+ 0 - 439
plot/DataCenter.py

@@ -1,439 +0,0 @@
-import os
-import time as stime
-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
-import time as time
-
-
-class DataCenter(object):
-    latest_delta = 10
-    pos_map = {
-        'commit-succ': 0, 'commit-fail': 1, 'notify-succ': 2, 'notify-fail': 3, 'user_succ': 4
-    }
-
-    def __init__(self):
-        self._mquit = False
-        self._mRHost = ''
-        self._mRPort = 6379
-        self._file_name = '/var/www/html/data/stdata/data.hdf5'
-
-    def set_redis(self, rhost, rport):
-        self._mRHost = rhost
-        self._mRPort = rport
-
-    def stop(self):
-        self._mquit = True
-        pass
-
-    def prepare_data(self):
-        while self._mquit == False:
-            try:
-                pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, 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')
-
-                latest_time = int(stime.time()) - self.latest_delta
-                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', latest_time)
-                self.del_redis(r, 'nc_channel_monitor_notify', latest_time)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(1)
-
-    def del_redis(self, redis, name,latest_time):
-        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
-        hfive[path][pos, diff] = val
-        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:
-            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, 8))
-            ax = fig.subplots()
-
-            x = np.arange(0, 86400, interval)
-
-            filer_text, paths = self.datasets(hfive, start_time, **kwargs)
-            sub_count = 0
-
-            predata = np.zeros((5, 86400))
-            for path, data in self.read_data(hfive, paths):
-                data = np.array(data)
-                predata = predata + data
-                ret = self._draw_plot(ax, x, day_stamp, start_pos, end_pos, data, interval, path)
-                if ret:
-                    sub_count += 1
-
-            if sub_count > 1:
-                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()
-            fig.subplots_adjust(left=0.05, right=0.999, top=0.95, bottom=0.1)
-
-            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 '', []
-
-        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
-            elif 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=''):
-        # 'commit-succ': 0, 'commit-fail': 1, 'notify-succ': 2, 'notify-fail': 3, 'user_succ': 4
-        logging.getLogger('app').debug("path=%s", path)
-        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)
-
-        if end_pos == -1:
-            pos = np.where(x >= start_pos)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-        else:
-            pos = np.where(start_pos <= x)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-
-            pos = np.where(x < end_pos)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-
-        succ_count = int(np.sum(ySucc))
-        all_count = int(np.sum(all))
-
-        opened = np.where(ySucc > 0.1)
-        if len(opened[0]) == 0:
-            logging.getLogger('app').debug("path=%s,opened=False", path)
-            return False
-
-        ySucc = ySucc / all
-        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=self._label(path, succ_count, all_count))
-        return True
-
-    def _label(self, path, count, all):
-        ratio = 0.00
-        if all > 0:
-            ratio = round(count * 100 / all, 2)
-
-        items = re.split(r'/', path)
-        if len(items) == 6:
-            (_, _sday, _chname, _quality, _card_type, _amount) = items
-            card_type = ''
-            if _card_type == '1':
-                card_type = 'SY'
-            elif _card_type == '2':
-                card_type = 'SH'
-            elif _card_type == '4':
-                card_type = 'YD'
-            elif _card_type == '5':
-                card_type = 'LT'
-            elif _card_type == '6':
-                card_type = 'DX'
-            elif _card_type == '7':
-                card_type = 'TH'
-            return f"{_chname}-{_quality}-{card_type}-{_amount}:{count}/{all} = {ratio}%"
-        else:
-            if path == '' or path is None:
-                path = 'average'
-            return f"{path}:{count}/{all} = {ratio}%"
-
-    def _cur_min(self):
-        time_sec = int(time.time())
-        cur_min = time_sec - time_sec % 60
-        return cur_min
-
-    def _calc_tuple(self, data, start_pos, end_pos):
-        # 'commit-succ': 0, 'commit-fail': 1, 'notify-succ': 2, 'notify-fail': 3, 'user_succ': 4
-        logging.getLogger('app').debug("path=%s", path)
-        cur_data = data[:, start_pos:end_pos]
-        all = np.sum(cur_data, axis=1)
-        all = all.tolist()
-
-        result = [int(x) for x in all]
-        return result[:4]
-
-    def _repath(self, path):
-        items = re.split(r'/', path)
-        if len(items) == 6:
-            (_, _sday, _chname, _quality, _card_type, _amount) = items
-            return f"{_chname}-{_amount}-{_card_type}-{_quality}"
-        else:
-            return False
-
-    def _calc_ratio(self, start_time, end_time):
-        hfive = None
-        try:
-            hfive = h5py.File(self._file_name, 'r')
-            day_stamp = self.day_stamp(start_time)
-            start_pos = start_time - day_stamp
-            end_pos = end_time - day_stamp
-
-            result = {'time': end_time}
-
-            ratios = {}
-            filer_text, paths = self.datasets(hfive, start_time)
-
-            if len(paths) == 0:
-                return None
-
-            for path, data in self.read_data(hfive, paths):
-                data = np.array(data)
-                ratio = self._calc_tuple(data, start_pos, end_pos)
-                key = self._repath(path)
-                ratios[key] = ratio
-                print(path, ratio)
-            result['ratios'] = ratios
-
-            return result
-        except Exception as ex:
-            print(ex)
-        finally:
-            hfive.close()
-        pass
-
-    def calc_ratio(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-        except Exception as ex:
-            print(ex)
-
-        while True:
-            try:
-                time_sec = int(time.time())
-                day_stamp = self.day_stamp(time_sec)
-
-                start_time = 0
-                if time_sec > day_stamp + 901:
-                    start_time = time_sec - 901
-                elif time_sec > day_stamp + 301:
-                    start_time = day_stamp
-                else:
-                    pass
-
-                self.log_time(day_stamp,time_sec,start_time)
-                if start_time >= day_stamp:
-                    ratios = self._calc_ratio(start_time=start_time, end_time=time_sec - 1)
-                    print('ratios=',ratios)
-                    if ratios != None:
-                        r.set(f"nc_channel_ratios", json.dumps(ratios))
-                        r.publish('refill',json.dumps({'type':'ratio','value':0}))
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(1)
-
-    def log_time(self,day_stamp, time_sec, start_time):
-        d = time.asctime(time.localtime(day_stamp))
-        a = time.asctime(time.localtime(time_sec))
-        b = time.asctime(time.localtime(start_time))
-        print('day_stamp=', d, 'cur_time=', a, 'start_time=', b)
-
-    def pub_ratio(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-            r.publish('refill',json.dumps({'type':'ratio','value':0}))
-        except Exception as ex:
-            print(ex)
-
-dataCenter = DataCenter()

+ 0 - 76
plot/Fetcher.py

@@ -1,76 +0,0 @@
-import time as stime
-import redis
-import h5py
-from os import path
-from datetime import timedelta
-
-class Fetcher(object):
-    latest_delta = 2
-
-    def __init__(self, file_name):
-        self._mquit = False
-        self._mRHost = ''
-        self._mRPort = 6379
-        self._file_name = file_name
-
-    def set_redis(self, rhost, rport):
-        self._mRHost = rhost
-        self._mRPort = rport
-
-    def stop(self):
-        self._mquit = True
-        pass
-
-    def redis_name_prefix(self) -> dict:
-        pass
-
-    def run(self):
-        while self._mquit == False:
-            fAllEmpty = True
-            try:
-                pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, 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')
-
-                latest_time = int(stime.time()) - self.latest_delta
-                name_prefix = self.redis_name_prefix()
-
-                for name, prefix in name_prefix.items():
-                    fEmpty = self.fetch_hset(hfive, r, name, prefix, latest_time)
-                    if fEmpty == False:
-                        fAllEmpty = False
-                hfive.close()
-            except Exception as ex:
-                print(ex)
-            finally:
-                if fAllEmpty:
-                    stime.sleep(1)
-
-    def parase(self, hfive, key, val, prefix, latest_time):
-        pass
-
-    def fetch_hset(self, hfive, redis, name, prefix, latest_time):
-        i = 0
-        fEmpty = True
-        for item in redis.hscan_iter(name):
-            fEmpty = False
-            key = str(item[0], encoding="utf-8")
-            val = str(item[1], encoding="utf-8")
-            print(f'{prefix}:{i}')
-            i += 1
-            fDel = self.parase(hfive, key, val, prefix, latest_time)
-            if fDel:
-                redis.hdel(name, key)
-
-        return fEmpty
-
-    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)

+ 0 - 681
plot/MchDataCenter.py

@@ -1,681 +0,0 @@
-import os
-import time as stime
-import redis
-import h5py
-from os import path
-import re
-from datetime import timedelta
-from datetime import datetime
-import numpy as np
-from matplotlib.figure import Figure
-from matplotlib import ticker
-from io import BytesIO
-import logging
-
-class MchDataCenter(object):
-    latest_delta = 10
-    pos_map = {
-        'commit': 0, 'success': 1, 'fail': 2
-    }
-
-    def __init__(self):
-        self._mquit = False
-        self._mRHost = ''
-        self._mRPort = 6379
-        self._file_name = '/var/www/html/data/stdata/user.hdf5'
-
-    def set_redis(self, rhost, rport):
-        self._mRHost = rhost
-        self._mRPort = rport
-
-    def stop(self):
-        self._mquit = True
-        pass
-
-    def prepare_data(self):
-        while self._mquit == False:
-            try:
-                pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, 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')
-
-                latest_time = int(stime.time()) - self.latest_delta
-                lt = stime.localtime(latest_time)
-                now_str = stime.strftime('%Y-%m-%d %H:%M:%S', lt)
-
-                print('start read',now_str)
-                self.read_redis(hfive, r, 'nc_user_monitor_commit', 'commit')
-                self.read_redis(hfive, r, 'nc_user_monitor_success', 'success')
-                self.read_redis(hfive, r, 'nc_user_monitor_fail', 'fail')
-                hfive.close()
-
-                self.del_redis(r, 'nc_user_monitor_commit',latest_time)
-                self.del_redis(r, 'nc_user_monitor_success',latest_time)
-                self.del_redis(r, 'nc_user_monitor_fail',latest_time)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(1)
-
-    def del_redis(self, redis, name, latest_time):
-        for item in redis.hscan_iter(name):
-            key = str(item[0], encoding="utf-8")
-            items = re.split(r'-', key)
-
-            flag_del = True
-            if len(items) == 5:
-                (mchid, quality, card_type, amount, time) = items
-                time = int(time)
-                if latest_time <= time:
-                    flag_del = False
-            else:
-                print('delete one error key:', key)
-
-            if flag_del:
-                redis.hdel(name, key)
-        pass
-
-    def read_redis(self, hfive, redis, name, prefix):
-        for item in redis.hscan_iter(name):
-            key = str(item[0], encoding="utf-8")
-            val = str(item[1], encoding="utf-8")
-            self.parase(hfive, key, val, prefix)
-
-    def parase(self, hfive, text, val, prefix):
-        items = re.split(r'-', text)
-        if len(items) != 5:
-            return False
-
-        (mchid, quality, card_type, amount, time) = items
-        pos = self.pos_map[f'{prefix}']
-
-        time = int(time)
-        today = self.day_stamp(time)
-        path = f'/{today}/{mchid}/{quality}/{card_type}/{amount}'
-        if path not in hfive:
-            dim = len(self.pos_map)
-            hfive[path] = np.zeros((dim, 86400))
-
-        diff = time - today
-        if diff < 0:
-            print(diff)
-        hfive[path][pos, diff] = val
-        print(path, pos, prefix, diff, time, 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 _all_none(self, **kwargs):
-        for key, val in kwargs.items():
-            if val is not None:
-                return False
-        return True
-
-    def _merge_path(self,paths):
-        result = {}
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-
-            _mchid = int(_mchid)
-            if _mchid not in result:
-                result[_mchid] = []
-            result[_mchid].append(path)
-
-        return result
-
-    def draw_plot(self, start_time, interval=300, **kwargs):
-        logger = logging.getLogger('app')
-        hfive = h5py.File(self._file_name, 'r')
-        try:
-            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, 8))
-            ax = fig.subplots()
-
-            dim = len(self.pos_map)
-            predata = np.zeros((dim, 86400))
-            x = np.arange(0, 86400, interval)
-
-            sub_count = 0
-            filer_text, paths = self.datasets(hfive, start_time, **kwargs)
-            if self._all_none(**kwargs):
-                paths = self._merge_path(paths)
-                for mchid, data in self._read_dict_data(hfive, paths):
-                    predata = predata + data
-                    path = f'{mchid}'
-                    ret = self._draw_plot(ax, x, day_stamp, start_pos, end_pos, data, interval, path)
-                    if ret:
-                        sub_count += 1
-                pass
-            else:
-                for path, data in self.read_data(hfive, paths):
-                    data = np.array(data)
-                    predata = predata + data
-                    ret = self._draw_plot(ax, x, day_stamp, start_pos, end_pos, data, interval, path)
-                    if ret:
-                        sub_count += 1
-            if sub_count > 1:
-                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()
-            fig.subplots_adjust(left=0.05, right=0.999, top=0.95, bottom=0.1)
-
-            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 _read_dict_data(self, hfive, mchPaths):
-        for mchid, paths in mchPaths.items():
-            dim = len(self.pos_map)
-            predata = np.zeros((dim, 86400))
-            for path in paths:
-                predata += hfive[path]
-            yield mchid, predata
-
-    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)
-
-        mchid = quality = card_type = amount = None
-        for key, val in kwargs.items():
-            if val is None:
-                continue
-            if key == 'mchid':
-                mchid = 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, mchid=mchid, quality=quality, card_type=card_type, amount=amount)
-
-    def _filter(self, dsets, mchid=None, quality=None, card_type=None, amount=None):
-        filer_text = ''
-        if mchid is not None:
-            filer_text = mchid
-        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, _mchid, _quality, _card_type, _amount) = items
-            if (mchid is not None) and (_mchid != mchid):
-                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=''):
-        # 'commit': 0, 'succ': 1, 'fail': 2
-        logging.getLogger('app').debug("path=%s", path)
-
-        all = data[1] + data[2]
-        all = all.reshape((-1, interval))
-        all = np.sum(all, axis=1)
-
-        commit = data[0]
-        commit = commit.reshape((-1, interval))
-        commit = np.sum(commit, axis=1)
-
-        ySucc = data[1]
-        ySucc = ySucc.reshape((-1, interval))
-        ySucc = np.sum(ySucc, axis=1)
-
-        yFail = data[2]
-        yFail = yFail.reshape((-1, interval))
-        yFail = np.sum(yFail, axis=1)
-
-        if end_pos == -1:
-            pos = np.where(x >= start_pos)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-            commit = commit[pos]
-            yFail = yFail[pos]
-        else:
-            pos = np.where(start_pos <= x)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-            commit = commit[pos]
-            yFail = yFail[pos]
-
-            pos = np.where(x < end_pos)
-            x = x[pos]
-            ySucc = ySucc[pos]
-            all = all[pos]
-            commit = commit[pos]
-            yFail = yFail[pos]
-
-        succ_count = int(np.sum(ySucc))
-        all_count  = int(np.sum(all))
-        commit_count = int(np.sum(commit))
-        fail_count = int(np.sum(yFail))
-
-        if all_count < 1:
-            return False
-
-        pos = np.where(ySucc > all)
-        ySucc[pos] = all[pos]
-
-        ySucc = ySucc / (all + 0.00000001)
-        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=self._label(path, succ_count, all_count,commit_count,fail_count))
-        return True
-
-    def _label(self, path, succ_count, all, commit_count, fail_count):
-        ratio = 0.00
-        if all > 0:
-            ratio = round(succ_count * 100 / all, 2)
-
-        items = re.split(r'/', path)
-        if len(items) == 6:
-            (_, _sday, _chname, _quality, _card_type, _amount) = items
-            card_type = ''
-            if _card_type == '1':
-                card_type = 'SY'
-            elif _card_type == '2':
-                card_type = 'SH'
-            elif _card_type == '4':
-                card_type = 'YD'
-            elif _card_type == '5':
-                card_type = 'LT'
-            elif _card_type == '6':
-                card_type = 'DX'
-            elif _card_type == '7':
-                card_type = 'TH'
-            return f"{_chname}-{_quality}-{card_type}-{_amount}:{succ_count}/{all} = {ratio}% {commit_count}:{fail_count}"
-        else:
-            if path == '' or path is None:
-                path = 'average'
-            return f"{path}:{succ_count}/{all} = {ratio}% {commit_count}:{fail_count}"
-        pass
-
-    #统计机构当前时间之前序列时间成功率
-    def _merge_mobile_path(self,paths):
-        result = {}
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-
-            _card_type = int(_card_type)
-            if _card_type not in [4, 5, 6]:
-                continue
-
-            _mchid = int(_mchid)
-            if _mchid not in result:
-                result[_mchid] = []
-            result[_mchid].append(path)
-        return result
-
-    def _merge_data(self, hfive, paths):
-        dim = len(self.pos_map)
-        predata = np.zeros((dim, 86400))
-        for path in paths:
-            predata += hfive[path]
-        return predata
-
-    def _calc_mratio(self,data,startes,end):
-        succ = data[1]
-        fail = data[2]
-        x = np.arange(0, 86400, 1)
-
-        result = {}
-        for start in startes:
-            if end - start < 0:
-                start_pos = 0
-            else:
-                start_pos = end - start
-
-            pos = np.where(x >= start_pos)
-            t = x[pos]
-            _fail = fail[pos]
-            _succ = succ[pos]
-
-            pos = np.where(t < end)
-            _fail = _fail[pos]
-            _succ = _succ[pos]
-
-            succs = int(np.sum(_succ))
-            fails  = int(np.sum(_fail))
-            ratio = round((succs + 0.00001) / (succs + fails + 0.00001), 4)
-            result[start] = [succs, fails, ratio]
-        return result
-
-    def mratios(self, time_stamp,presecs):
-        paths = self.paths(time_stamp)
-        mchid_paths = self._merge_mobile_path(paths)
-        day_stamp = self.day_stamp(time_stamp)
-
-        mratios = {}
-        hfive = h5py.File(self._file_name, 'r')
-        for mchid, paths in mchid_paths.items():
-            mdata = self._merge_data(hfive,paths)
-            result = self._calc_mratio(mdata,presecs,time_stamp - day_stamp)
-            mratios[mchid] = result
-        hfive.close()
-        return mratios
-
-    def calc_ratio(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-        except Exception as ex:
-            print(ex)
-
-        while True:
-            try:
-                time_sec = int(stime.time())
-                presecs = [900, 1800, 3600, 7200, 86400]
-                mratios = self.mratios(time_sec, presecs)
-
-                if len(mratios) != 0:
-                    r.set(f"nc_merchant_ratios", json.dumps(mratios))
-                    r.publish('refill',json.dumps({'type':'mch_ratio','value':0}))
-                    print('push msg=',mratios)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(2)
-
-    #以下为按照卡类型计算成功率代码
-    def _merge_mobile_type_path(self,paths,card_type=None):
-        result = {}
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-
-            _card_type = int(_card_type)
-            if _card_type not in [4, 5, 6]:
-                continue
-            if card_type is not None and _card_type != card_type:
-                continue
-
-            _mchid = int(_mchid)
-            if _mchid not in result:
-                result[_mchid] = []
-            result[_mchid].append(path)
-        return result
-
-    def mratio_types(self, time_stamp,presecs):
-        paths = self.paths(time_stamp)
-
-        mchid_paths = self._merge_mobile_type_path(paths)
-        day_stamp = self.day_stamp(time_stamp)
-
-        card_types = {None: 'ALL', 4: 'YD', 5: 'LT', 6: 'DX'}
-
-        mratios = {}
-        hfive = h5py.File(self._file_name, 'r')
-        for mchid, paths in mchid_paths.items():
-            mch_ratios = {}
-            for card_type, name in card_types.items():
-                print('card_type=', card_type, 'name=', name)
-                if card_type is None:
-                    cur_paths = paths
-                else:
-                    cur_paths = self._merge_mobile_type_path(paths, card_type)
-                    if len(cur_paths) == 0:
-                        continue
-                    cur_paths = cur_paths[mchid]
-                mdata = self._merge_data(hfive,cur_paths)
-                result = self._calc_mratio(mdata,presecs,time_stamp - day_stamp)
-                mch_ratios[name] = result
-            mratios[mchid] = mch_ratios
-        hfive.close()
-        return mratios
-
-    def calc_ratios(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-        except Exception as ex:
-            print(ex)
-
-        while True:
-            try:
-                time_sec = int(stime.time())
-                presecs = [900, 1800, 3600, 7200, 86400]
-                mratios = self.mratio_types(time_sec, presecs)
-
-                if len(mratios) != 0:
-                    r.set(f"nc_merchant_card_type_ratios", json.dumps(mratios))
-                    # r.publish('refill',json.dumps({'type':'mch_ratio','value':0}))
-                    print('push msg=', mratios)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(2)
-
-    ####################################################################################################################
-    ####
-    def _calc_mcount(self,data,startes,end):
-        succ = data[1]
-        fail = data[2]
-        x = np.arange(0, 86400, 1)
-
-        result = {}
-        for start in startes:
-            if end - start < 0:
-                start_pos = 0
-            else:
-                start_pos = end - start
-
-            pos = np.where(x >= start_pos)
-            t = x[pos]
-            _succ = succ[pos]
-            _fail = fail[pos]
-
-            pos = np.where(t < end)
-            _succ = _succ[pos]
-            _fail = _fail[pos]
-
-            succs = int(np.sum(_succ))
-            fails = int(np.sum(_fail))
-            ratio = round((succs + 0.00001) / (succs + fails + 0.00001), 4)
-            result[start] = [succs, fails, ratio]
-        return result
-
-    def merchant_rmobile_path(self, paths):
-        result = {}
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-
-            _card_type = int(_card_type)
-            if _card_type not in [4, 5, 6]:
-                continue
-
-            _mchid = int(_mchid)
-            if _mchid not in result:
-                result[_mchid] = []
-            result[_mchid].append(path)
-        return result
-
-    def rmobile_path(self, paths):
-        result = []
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-
-            _card_type = int(_card_type)
-            if _card_type not in [4, 5, 6]:
-                continue
-            result.append(path)
-        return result
-
-    def mch_count(self, paths, presecs,time_stamp):
-        hfive = h5py.File(self._file_name, 'r')
-        mdata = self._merge_data(hfive,paths)
-        day_stamp = self.day_stamp(time_stamp)
-        result = self._calc_mcount(mdata,presecs,time_stamp - day_stamp)
-        hfive.close()
-
-        return result
-
-    def mch_detail_count(self, paths, presecs,time_stamp):
-        hfive = h5py.File(self._file_name, 'r')
-
-        result = {}
-        for path in paths:
-            items = re.split(r'/', path)
-            if len(items) != 6:
-                continue
-            (_, _sday, _mchid, _quality, _card_type, _amount) = items
-            key = f"{_mchid}-{_quality}-{_card_type}-{_amount}"
-            mdata = hfive[path]
-            day_stamp = self.day_stamp(time_stamp)
-            result[key] = self._calc_mcount(mdata,presecs,time_stamp - day_stamp)
-        hfive.close()
-        return result
-
-    def mch_counts(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-        except Exception as ex:
-            print(ex)
-
-        while True:
-            try:
-                time_stamp = int(stime.time())
-                presecs = [900, 1800, 3600, 7200, 86400]
-                all_paths = self.paths(time_stamp)
-                mchid_paths = self.merchant_rmobile_path(all_paths)
-
-                gross = {}
-                for mchid, paths in mchid_paths.items():
-                    counts = self.mch_count(paths, presecs, time_stamp)
-                    gross[mchid] = counts
-
-                paths = self.rmobile_path(all_paths)
-                detail = self.mch_detail_count(paths, presecs, time_stamp)
-
-                result = {'gross': gross, 'detail': detail}
-                if len(result) != 0:
-                    r.set(f"nc_merchant_refill_counts", json.dumps(result))
-                    r.publish('refill',json.dumps({'type':'mch_counts','value':0}))
-                    print('push msg=', result)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(2)
-
-mchDataCenter = MchDataCenter()

+ 0 - 9
plot/Singleton.py

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

+ 0 - 185
plot/SpeedDataCenter.py

@@ -1,185 +0,0 @@
-import os
-import time as stime
-import redis
-import h5py
-from os import path
-import re
-from datetime import timedelta
-from datetime import datetime
-import numpy as np
-
-class SpeedDataCenter(object):
-    latest_delta = 10
-    def __init__(self):
-        self._mquit = False
-        self._mRHost = ''
-        self._mRPort = 6379
-        self._file_name = '/var/www/html/data/stdata/speed.hdf5'
-
-    def set_redis(self, rhost, rport):
-        self._mRHost = rhost
-        self._mRPort = rport
-
-    def stop(self):
-        self._mquit = True
-        pass
-
-    def prepare_data(self):
-        pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-        r = redis.Redis(connection_pool=pool)
-
-        while self._mquit == False:
-            try:
-                print('open file:', datetime.now())
-                if path.exists(self._file_name):
-                    hfive = h5py.File(self._file_name, 'a')
-                else:
-                    hfive = h5py.File(self._file_name, 'w')
-
-                latest_time = int(stime.time()) - self.latest_delta
-                print('read redis:', datetime.now())
-                self.read_redis(hfive, r, 'nc_commit_speed_monitor')
-                hfive.close()
-
-                print('del redis:', datetime.now())
-                self.del_redis(r, 'nc_commit_speed_monitor',latest_time)
-                print('del redis:', datetime.now())
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(1)
-
-    def del_redis(self, redis, name,latest_time):
-        for item in redis.hscan_iter(name):
-            key = str(item[0], encoding="utf-8")
-            items = re.split(r'-', key)
-            fdel = True
-            if len(items) == 5:
-                (chname, quality, card_type, amount, time) = items
-                time = int(time)
-                if time > latest_time:
-                    fdel = False
-            if fdel:
-                redis.hdel(name, key)
-        pass
-
-    def read_redis(self, hfive, redis, name):
-        for item in redis.hscan_iter(name):
-            key = str(item[0], encoding="utf-8")
-            val = str(item[1], encoding="utf-8")
-            self.parase(hfive, key, val)
-
-    def parase(self, hfive, text, val):
-        items = re.split(r'-', text)
-        if len(items) != 5:
-            return False
-
-        (chname, quality, card_type, spec, time) = items
-        time = int(time)
-        today = self.day_stamp(time)
-        path = f'/{today}/{chname}/{quality}/{card_type}/{spec}'
-        if path not in hfive:
-            hfive[path] = np.zeros((1, 86400))
-
-        diff = time - today
-        hfive[path][0, diff] = val
-        print(path, 0, diff, val, hfive[path][0, 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 channl_speed(self):
-        import json
-
-        r = None
-        try:
-            pool = redis.ConnectionPool(host=self._mRHost, port=self._mRPort, db=0)
-            r = redis.Redis(connection_pool=pool)
-        except Exception as ex:
-            print(ex)
-
-        while True:
-            try:
-                time_stamp = int(stime.time())
-                paths = self.paths(time_stamp)
-                day_stamp = self.day_stamp(time_stamp)
-                (pos_start, pos_end) = self._pos_range(time_stamp - day_stamp)
-
-                hfive = h5py.File(self._file_name, 'r')
-                result = {}
-                for path in paths:
-                    key = self._parse_path(path)
-                    speed = self._calc_speed(hfive, path, pos_start, pos_end)
-                    result[key] = speed
-                    pass
-                hfive.close()
-
-                if len(result) != 0:
-                    r.set(f"nc_channels_speed", json.dumps(result))
-                    r.publish('refill', json.dumps({'type': 'channels_speed', 'value': 0}))
-                    print(datetime.now(), 'push msg=', result)
-            except Exception as ex:
-                print(ex)
-            finally:
-                stime.sleep(0.1)
-
-    def _parse_path(self,path):
-        items = re.split(r'/', path)
-        if len(items) != 6:
-            return False
-        (_, _sday, _chname, _quality, _card_type, _spec) = items
-        key = f'{_chname}-{_spec}-{_card_type}-{_quality}' #接收端的key,是如此定义的
-        return key
-
-    def _pos_range(self,end):
-        pos_day = np.arange(0, 86400, 1)
-
-        period = 60
-        if end - period > 0:
-            start = end - period
-            pos_start = np.where(pos_day > start)
-        else:
-            start = 0
-            pos_start = np.where(pos_day >= start)
-
-        pos_day = pos_day[pos_start]
-        pos_end = np.where(pos_day <= end)
-
-        return pos_start, pos_end
-
-    def _calc_speed(self,hFive,path,pos_start, pos_end):
-        datas = hFive[path]
-        commit = datas[0]
-        commit = commit[pos_start]
-        commit = commit[pos_end]
-        speed = int(np.sum(commit))
-        return speed
-
-    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
-
-speedDataCenter = SpeedDataCenter()

+ 0 - 52
plot/UserFetcher.py

@@ -1,52 +0,0 @@
-
-from Fetcher import Fetcher
-import re
-import numpy as np
-
-class UserFetcher(Fetcher):
-    #0纬放所有数据,1纬放成功,2纬放失败
-    pos_map = {
-        'commit': 0, 'success': 1, 'fail': 2
-    }
-
-    name_prefix = {
-        'nc_user_monitor_commit': 'commit',
-        'nc_user_monitor_success': 'success',
-        'nc_user_monitor_fail': 'fail'
-    }
-
-    def __init__(self):
-        filename = '/var/www/html/data/stdata/user.hdf5'
-        super().__init__(filename)
-        pass
-
-    def redis_name_prefix(self) -> dict:
-        return self.name_prefix
-
-    def parase(self, hfive, key, val, prefix,latest_time):
-        items = re.split(r'-', key)
-        if len(items) != 5:
-            return True
-
-        (mchid, quality, card_type, amount, time) = items
-        pos = self.pos_map[f'{prefix}']
-
-        time = int(time)
-        today = self.day_stamp(time)
-        path = f'/{today}/{mchid}/{quality}/{card_type}/{amount}'
-        if path not in hfive:
-            dim = len(self.pos_map)
-            hfive[path] = np.zeros((dim, 86400))
-
-        diff = time - today
-        if diff < 0:
-            print(diff)
-        hfive[path][pos, diff] = val
-        print(path, pos, diff, val, hfive[path][pos, diff])
-
-        if time > latest_time:
-            return False
-        else:
-            return True
-        pass
-    pass

+ 67 - 110
plot/app.py

@@ -3,10 +3,6 @@ import base64
 from io import BytesIO
 from matplotlib.figure import Figure
 import json
-from DataCenter import dataCenter
-from MchDataCenter import mchDataCenter
-
-# from plog import initLog
 from flask import request, jsonify
 import logging
 from logging.handlers import RotatingFileHandler
@@ -15,7 +11,7 @@ import signal as sig
 import sys, getopt
 
 app = Flask(__name__)
-app.debug = True
+app.debug = False
 
 curname = __name__
 
@@ -24,8 +20,10 @@ logging.basicConfig(filename='/var/www/html/data/log/flask.log',
                     level=logging.DEBUG)
 logger = logging.getLogger('plot')
 
-from refill import ChannelCumPainter, MerchantPainter, ChannelCovPainter
+from refill import ChannelCumPainter, ChannelCovPainter, ChannelCovSuccPainter
+from refill import MerchantCumRatioPainter, MerchantAmountPainter, MerchantCovRatioPainter
 from refill import filter_chname, filter_cardtype, filter_mchids, get_channels, get_mchids
+from refill import NetcheckCovPainter, get_net_channels
 
 
 def parse_parmeter():
@@ -90,10 +88,45 @@ def ch_covratio():
         return onError(ex)
 
 
-@app.route('/plot/channels')
-def channels():
+@app.route('/plot/ch_covsuccs')
+def ch_covsuccs():
+    try:
+        logger.debug('start ch_covratio')
+        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
+        chnames = request.args.get('chnames')
+        chnames = filter_chname(chnames)
+
+        painter = ChannelCovSuccPainter(start_time=start_time, end_time=end_time, chnames=chnames, card_types=card_types, spec=spec,
+                                        filter_wave=filter_wave)
+        buf, ratios = painter.paint()
+        data = base64.b64encode(buf.getbuffer()).decode("ascii")
+
+        return jsonify({'img': data, 'ratios': ratios, 'state': 'success'})
+    except Exception as ex:
+        return onError(ex)
+
+
+@app.route('/plot/net_check')
+def net_check():
+    try:
+        logger.debug('start net_check')
+        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
+        chnames = request.args.get('chnames')
+        chnames = filter_chname(chnames)
+
+        painter = NetcheckCovPainter(start_time=start_time, end_time=end_time, chnames=chnames, filter_wave=filter_wave)
+        buf, ratios = painter.paint()
+        data = base64.b64encode(buf.getbuffer()).decode("ascii")
+
+        return jsonify({'img': data, 'ratios': ratios, 'state': 'success'})
+    except Exception as ex:
+        return onError(ex)
+
+
+@app.route('/plot/net_channels')
+def net_channels():
     try:
-        channels = get_channels()
+        channels = get_net_channels()
         return jsonify(channels)
     except Exception as ex:
         logger.error(ex)
@@ -118,8 +151,27 @@ def mch_ratio():
         mchids = request.args.get('mchids')
         mchids = filter_mchids(mchids)
 
-        painter = MerchantPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec, filter_wave=filter_wave)
-        buf, ratios = painter.paint_ratios()
+        painter = MerchantCumRatioPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec,
+                                          filter_wave=filter_wave)
+        buf, ratios = painter.paint()
+        data = base64.b64encode(buf.getbuffer()).decode("ascii")
+
+        return jsonify({'img': data, 'ratios': ratios, 'state': 'success'})
+    except Exception as ex:
+        return onError(ex)
+
+
+@app.route('/plot/mch_covratio')
+def mch_covratio():
+    try:
+        logger.debug('start mchratio')
+        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
+        mchids = request.args.get('mchids')
+        mchids = filter_mchids(mchids)
+
+        painter = MerchantCovRatioPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec,
+                                          filter_wave=filter_wave)
+        buf, ratios = painter.paint()
         data = base64.b64encode(buf.getbuffer()).decode("ascii")
 
         return jsonify({'img': data, 'ratios': ratios, 'state': 'success'})
@@ -135,112 +187,17 @@ def mch_order_send():
         mchids = request.args.get('mchids')
         mchids = filter_mchids(mchids)
 
-        painter = MerchantPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec, filter_wave=filter_wave)
-        buf, mchids = painter.paint_refilling()
+        painter = MerchantAmountPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec,
+                                        filter_wave=filter_wave)
+        buf, mchids = painter.paint()
         data = base64.b64encode(buf.getbuffer()).decode("ascii")
         return jsonify({'img': data, 'mchids': mchids, 'state': 'success'})
     except Exception as ex:
         return onError(ex)
 
 
-@app.route('/plot/index')
-def index():
-    app.logger.debug('start')
-    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(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():
-    s_time = time.time()
-    dates = dataCenter.days()
-    e_time = time.time()
-    print('time=', e_time - s_time)
-    dates.reverse()
-    dates = dates[0:30]
-    return jsonify(dates)
-
-
-@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)
-
-
-@app.route('/plot/mchdays')
-def mchdays():
-    dates = mchDataCenter.days()
-    dates.reverse()
-    dates = dates[0:30]
-    return jsonify(dates)
-
-
-@app.route('/plot/mchpaths')
-def mchpaths():
-    time_stamp = request.args.get('time_stamp')
-    time_stamp = int(time_stamp)
-    paths = mchDataCenter.paths(time_stamp)
-    return jsonify(paths)
-
-
-@app.route('/plot/mchplot')
-def mchplot():
-    time_stamp = request.args.get('time_stamp')
-    interval = request.args.get('interval')
-    mchid = request.args.get('mchid')
-    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, mchid, 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 = mchDataCenter.draw_plot(time_stamp, interval=interval, mchid=mchid, quality=quality, card_type=card_type,
-                                  amount=amount)
-    data = base64.b64encode(buf.getbuffer()).decode("ascii")
-    return f"<img src='data:image/png;base64,{data}'/>"
-
-
 if __name__ == "__main__":
-    debug_mode = True
+    debug_mode = False
     if debug_mode:
         app.run(debug=True, host='0.0.0.0', port=5000)
     else:

+ 0 - 25
plot/chspeed.py

@@ -1,25 +0,0 @@
-import signal as sig
-import sys,getopt
-
-from SpeedDataCenter import speedDataCenter
-
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "h:p:", ["host=", 'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    speedDataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: speedDataCenter.stop())
-    speedDataCenter.channl_speed()

+ 0 - 25
plot/flask_test.py

@@ -1,25 +0,0 @@
-from flask import Flask
-from flask import request, jsonify
-
-app = Flask(__name__)
-
-import logging
-logging.basicConfig(filename='/var/www/html/data/log/flask.log',
-                    format='%(levelname)10s  %(asctime)s  %(name)10s %(thread)d %(message)s',
-                    level=logging.DEBUG)
-logger = logging.getLogger('plot')
-
-@app.route('/hello')
-def hello_world():
-    logger.debug('start chratio')
-    start_time = request.args.get('start_time') or None
-    end_time = request.args.get('end_time') or None
-    interval = request.args.get('interval') or None
-    chnames = request.args.get('chnames') or None
-    card_type = request.args.get('card_type') or None
-    spec = request.args.get('spec') or None
-    return 'Hello World'
-
-
-if __name__ == '__main__':
-    app.run(debug=True, host='0.0.0.0', port=5000)

+ 0 - 31
plot/mchreader.py

@@ -1,31 +0,0 @@
-import signal as sig
-import sys,getopt
-
-from MchDataCenter import mchDataCenter
-# from UserFetcher import UserFetcher
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],"h:p:",["host=",'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-            
-    mchDataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: mchDataCenter.stop())
-    mchDataCenter.prepare_data()
-
-    # fetcher  = UserFetcher()
-    # sig.signal(sig.SIGINT, lambda: fetcher.stop())
-    # fetcher.run()
-

+ 0 - 23
plot/mcounts.py

@@ -1,23 +0,0 @@
-from MchDataCenter import mchDataCenter
-import signal as sig
-import sys,getopt
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],"h:p:",["host=",'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    mchDataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: mchDataCenter.stop())
-    mchDataCenter.mch_counts()

+ 0 - 23
plot/mratio.py

@@ -1,23 +0,0 @@
-from MchDataCenter import mchDataCenter
-import signal as sig
-import sys,getopt
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],"h:p:",["host=",'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    mchDataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: mchDataCenter.stop())
-    mchDataCenter.calc_ratio()

+ 0 - 23
plot/mratios.py

@@ -1,23 +0,0 @@
-from MchDataCenter import mchDataCenter
-import signal as sig
-import sys,getopt
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "h:p:", ["host=", 'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    mchDataCenter.set_redis(rhost, rport)
-    sig.signal(sig.SIGINT, lambda: mchDataCenter.stop())
-    mchDataCenter.calc_ratios()

+ 19 - 0
plot/mtimesratio.py

@@ -0,0 +1,19 @@
+from refill import opt_parse, MTimesRatioCalc
+import signal as sig
+import logging
+
+logging.basicConfig(filename='/var/www/html/data/log/statcalc.log',
+                    format='%(levelname)10s  %(asctime)s  %(name)10s %(thread)d %(message)s',
+                    level=logging.DEBUG)
+
+logger = logging.getLogger('mprofit_ratio')
+
+if __name__ == '__main__':
+    try:
+        rhost, rport = opt_parse()
+        calc = MTimesRatioCalc()
+        calc.set_redis(rhost, rport)
+        sig.signal(sig.SIGINT, lambda: calc.stop())
+        calc.run()
+    except Exception as ex:
+        logger.error(ex)

+ 0 - 11
plot/plog.py

@@ -1,11 +0,0 @@
-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')

+ 0 - 128
plot/plot_control.py

@@ -1,128 +0,0 @@
-from flask import Flask, request, jsonify
-app = Flask(__name__)
-
-import base64
-from io import BytesIO
-from matplotlib.figure import Figure
-import json
-
-import logging
-import time
-import signal as sig
-import sys, getopt
-
-from refill import ChannelCumPainter,MerchantPainter
-from refill import filter_chname, filter_cardtype, filter_mchids, get_channels, get_mchids
-
-logging.basicConfig(filename='/var/www/html/data/log/flask.log',
-                    format='%(levelname)10s  %(asctime)s  %(name)10s %(thread)d %(message)s',
-                    level=logging.DEBUG)
-logger = logging.getLogger('plot')
-
-def parse_parmeter():
-    end_time = request.args.get('end_time')
-    end_time = None if end_time is None else int(end_time.strip())
-
-    start_time = request.args.get('start_time')
-    start_time = None if start_time is None else int(start_time.strip())
-
-    card_types = request.args.get('card_types')
-    card_types = filter_cardtype(card_types)
-
-    spec = request.args.get('spec')
-    if spec is not None:
-        spec = int(spec.strip())
-
-    filter_wave = request.args.get('filter_wave')
-    if filter_wave is not None:
-        filter_wave = int(filter_wave.strip())
-
-    return start_time,end_time,card_types,spec,filter_wave
-
-def onError(ex):
-    logger.error(ex)
-    data = base64.b64encode(b'').decode("ascii")
-    return f"<img src='data:image/png;base64,{data}'/>"
-
-
-@app.route('/plot/ch_ratio')
-def ch_ratio():
-    try:
-        logger.debug('start chratio')
-        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
-        chnames = request.args.get('chnames')
-        chnames = filter_chname(chnames)
-
-        painter = ChannelCumPainter(start_time=start_time, end_time=end_time, chnames=chnames, card_types=card_types, spec=spec, filter_wave=filter_wave)
-        buf = painter.paint()
-        data = base64.b64encode(buf.getbuffer()).decode("ascii")
-
-        return f"<img src='data:image/png;base64,{data}'/>"
-    except Exception as ex:
-        return onError(ex)
-
-@app.route('/plot/channels')
-def channels():
-    try:
-        channels = get_channels()
-        return jsonify(channels)
-    except Exception as ex:
-        logger.error(ex)
-        return jsonify([])
-
-@app.route('/plot/mchids')
-def mchids():
-    try:
-        mchids = get_mchids()
-        return jsonify(mchids)
-    except Exception as ex:
-        logger.error(ex)
-        return jsonify([])
-
-@app.route('/plot/mch_ratio')
-def mch_ratio():
-    try:
-        logger.debug('start mchratio')
-        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
-        mchids = request.args.get('mchids')
-        mchids = filter_mchids(mchids)
-
-        painter = MerchantPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec, filter_wave=filter_wave)
-        buf = painter.paint_ratios()
-        data = base64.b64encode(buf.getbuffer()).decode("ascii")
-
-        return f"<img src='data:image/png;base64,{data}'/>"
-    except Exception as ex:
-        return onError(ex)
-
-@app.route('/plot/mch_order_send')
-def mch_order_send():
-    try:
-        logger.debug('start mch_order_send')
-        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
-        mchids = request.args.get('mchids')
-        mchids = filter_mchids(mchids)
-
-        painter = MerchantPainter(start_time=start_time, end_time=end_time, mchids=mchids, card_types=card_types, spec=spec, filter_wave=filter_wave)
-        buf = painter.paint_refilling()
-        data = base64.b64encode(buf.getbuffer()).decode("ascii")
-
-        return f"<img src='data:image/png;base64,{data}'/>"
-    except Exception as ex:
-        return onError(ex)
-
-
-if __name__ == "__main__":
-    debug_mode = True
-    if debug_mode:
-        app.run(debug=True, host='0.0.0.0', port=5000)
-    else:
-        from gevent import monkey
-        from gevent.pywsgi import WSGIServer
-        from gevent import signal as geventsig
-
-        monkey.patch_all()
-        http_server = WSGIServer(('0.0.0.0', 5000), app)
-        geventsig.signal(sig.SIGTERM, lambda: http_server.stop())
-        geventsig.signal(sig.SIGINT, lambda: http_server.stop())
-        http_server.serve_forever()

+ 0 - 11
plot/pywsgi.py

@@ -1,11 +0,0 @@
-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()

+ 0 - 23
plot/ratio.py

@@ -1,23 +0,0 @@
-from DataCenter import dataCenter
-import signal as sig
-import sys,getopt
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],"h:p:",["host=",'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    dataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: dataCenter.stop())
-    dataCenter.calc_ratio()

+ 0 - 23
plot/reader.py

@@ -1,23 +0,0 @@
-from DataCenter import dataCenter
-import signal as sig
-import sys,getopt
-
-if __name__ == '__main__':
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],"h:p:",["host=",'port='])
-    except Exception as ex:
-        print(ex)
-        sys.exit(2)
-
-    rhost = ''
-    rport=6379
-    for o, val in opts:
-        if o in ("-h", "--host"):
-            rhost = val
-        elif o in ('-p', "--port"):
-            rport = int(val)
-        else:
-            print("Err argv")
-    dataCenter.set_redis(rhost,rport)
-    sig.signal(sig.SIGINT, lambda: dataCenter.stop())
-    dataCenter.prepare_data()

+ 0 - 0
plot/refill/ChSpeedRatioCalc.py


Деякі файли не було показано, через те що забагато файлів було змінено