2
0

9 Commits c425a5e0cf ... 80edf4b64f

Autor SHA1 Nachricht Datum
  stanley-king 80edf4b64f Merge branch 'raccount' into refill/price vor 1 Monat
  lowkeyman 1ff2e5b691 国创分省 广东移动调价 vor 1 Monat
  lowkeyman f75c8a62e9 Merge branch 'rch' into raccount vor 1 Monat
  lowkeyman 7c6630446c 椰林:南泰全国1号 ,南泰全国2号,南泰京东,南泰分省,椰椰快充3号 vor 1 Monat
  lowkeyman 4396872610 dev vor 1 Monat
  lowkeyman fcfbae57c3 国创分省 广东移动调价 vor 1 Monat
  lowkeyman f994559918 补单监控 检索 vor 1 Monat
  lowkeyman e0747b3873 Merge branch 'raccount' of 39.97.239.116:gyfl/xyzshop into raccount vor 1 Monat
  lowkeyman 4757cd7e88 补单监控 仅显示充值中和已取消(未返销)的数据 vor 1 Monat
35 geänderte Dateien mit 1946 neuen und 69 gelöschten Zeilen
  1. 50 65
      admin/control/ordersendlist.php
  2. 1 0
      admin/language/zh_cn/core_lang_index.php
  3. 3 3
      admin/templates/default/monitor_transfer.php
  4. 1 1
      admin/templates/default/refill_amount_stats.index.php
  5. 206 0
      data/config/yl/phone.ini.php
  6. 25 0
      data/model/refill_buyback.model.php
  7. BIN
      helper/refill/api/xyz/guochuang/20250307_yd_guangdong.jpg
  8. BIN
      helper/refill/api/xyz/guochuang/20250307_yd_guangdong2.jpg
  9. 39 0
      helper/refill/api/yl/nantai/API.MD
  10. 52 0
      helper/refill/api/yl/nantai/RefillCallBack.php
  11. 146 0
      helper/refill/api/yl/nantai/RefillPhone.php
  12. 47 0
      helper/refill/api/yl/nantai/config.php
  13. 64 0
      helper/refill/api/yl/nantai_fs/API.MD
  14. 52 0
      helper/refill/api/yl/nantai_fs/RefillCallBack.php
  15. 165 0
      helper/refill/api/yl/nantai_fs/RefillPhone.php
  16. 115 0
      helper/refill/api/yl/nantai_fs/config.php
  17. 27 0
      helper/refill/api/yl/nantai_jingdong/API.MD
  18. 52 0
      helper/refill/api/yl/nantai_jingdong/RefillCallBack.php
  19. 146 0
      helper/refill/api/yl/nantai_jingdong/RefillPhone.php
  20. 41 0
      helper/refill/api/yl/nantai_jingdong/config.php
  21. 38 0
      helper/refill/api/yl/nantai_sec/API.MD
  22. 52 0
      helper/refill/api/yl/nantai_sec/RefillCallBack.php
  23. 146 0
      helper/refill/api/yl/nantai_sec/RefillPhone.php
  24. 46 0
      helper/refill/api/yl/nantai_sec/config.php
  25. 14 0
      helper/refill/api/yl/yeyekcthreehv/API.MD
  26. 76 0
      helper/refill/api/yl/yeyekcthreehv/RefillCallBack.php
  27. 161 0
      helper/refill/api/yl/yeyekcthreehv/RefillPhone.php
  28. 13 0
      helper/refill/api/yl/yeyekcthreehv/config.php
  29. 4 0
      mobile/callback/refill_nantai.php
  30. 4 0
      mobile/callback/refill_nantai_fs.php
  31. 4 0
      mobile/callback/refill_nantai_jingdong.php
  32. 4 0
      mobile/callback/refill_nantai_sec.php
  33. 4 0
      mobile/callback/refill_yeyekcthreehv.php
  34. 30 0
      test/TestRefill.php
  35. 118 0
      test/TestTransferOrder.php

+ 50 - 65
admin/control/ordersendlist.php

@@ -223,13 +223,6 @@ class ordersendlistControl extends SystemControl
 
         $base_cond['refill_order.inner_status'] = 0;
 
-        if (in_array($_GET['order_state'], ['0', '10', '20', '30', '40'])) {
-            $base_cond['vr_order.order_state'] = intval($_GET['order_state']);
-        }
-//        else {
-//            $base_cond['vr_order.order_state'] = ['in', [ORDER_STATE_CANCEL, ORDER_STATE_SEND]];
-//        }
-
         $all_mchids = $this->getAllTransferMchid();
         if (!empty($_GET['mchid'])) {
             $base_cond['refill_order.mchid'] = $_GET['mchid'];
@@ -274,77 +267,69 @@ class ordersendlistControl extends SystemControl
             $base_cond['refill_order.order_time'] = ['egt', $start];
         }
 
+        //根据客户单号来识别订单是否返销
+        $mod_buyback = Model('refill_buyback');
+        $buyback_cond['refill_buyback.order_time'] = $base_cond['refill_order.order_time'];
+        $buyback_cond['refill_order.order_time'] = $base_cond['refill_order.order_time'];
+        $buyback_cond['vr_order.order_state'] = ORDER_STATE_SUCCESS;
+        $buyback_list = $mod_buyback->getAllBuybackOrder($buyback_cond, 'distinct refill_order.mch_order');
+        $buyback_mch_orders = array_column($buyback_list, 'mch_order');
+
+        $order_state = $_GET['order_state'];
+        if ($order_state === '-2' && !empty($buyback_mch_orders))
+        {
+            $base_cond['refill_order.mch_order'] = ['in', $buyback_mch_orders];
+        }
+        else if (in_array($_GET['order_state'], ['0', '30', '40']))
+        {
+            $base_cond['vr_order.order_state'] = intval($_GET['order_state']);
+        }
+        else if (empty($order_state))
+        { //没选择订单状态,默认只显示充值中和已取消(未返销)
+            $base_cond['vr_order.order_state'] = ['in', [ORDER_STATE_CANCEL, ORDER_STATE_SEND]];
+
+            if (!empty($buyback_mch_orders)) {
+                $base_cond['refill_order.mch_order'] = ['not in', $buyback_mch_orders];
+            }
+        }
+
         if (!empty($_GET['export'])) {
             $this->monitor_transfer_export($base_cond, $merchants_getter, $all_mchids);
             return;
         }
 
-        $cur_time = time();
-        $order_by = 'refill_order.order_time desc';
-        $order_list = Model('')->table('refill_order,vr_order,merchant')
-            ->join('inner,inner')
-            ->on('refill_order.order_id=vr_order.order_id,refill_order.mchid=merchant.mchid')
-            ->field("refill_order.*,vr_order.order_state,({$cur_time} - refill_order.order_time - merchant.time_out) as mtime_out")
-            ->where($base_cond)
-            ->order($order_by)
-            ->select();
-
-
-
-        $merchant_list = $merchants_getter($all_mchids);
-        if(!empty($order_list))
+        if ($order_state === '-2' && empty($buyback_mch_orders))
+        { //仅查询返销,不存在返销数据
+            $order_list = [];
+        }
+        else
         {
-            $order_list = $this->orderFormat($order_list, $merchant_list);
-
-            //补充订单的返销状态,按客户单号判断
-            $mch_orders = array_column($order_list,'mch_order');
-            $mch_orders = array_unique($mch_orders);
-
-            $relate_con = [
-                'refill_order.order_time' => $base_cond['refill_order.order_time'],
-                'refill_order.mch_order' => ['in', $mch_orders],
-                'vr_order.order_state' => ORDER_STATE_SUCCESS,
-                'refill_order.inner_status' => 0
-            ];
-            $relate_list = Model('')->table('refill_order,vr_order')
-                ->join('inner')
-                ->on('refill_order.order_id=vr_order.order_id')
-                ->field("refill_order.order_id,refill_order.mch_order")
-                ->where($relate_con)
+            $cur_time = time();
+            $order_by = 'refill_order.order_time desc';
+            $order_list = Model('')->table('refill_order,vr_order,merchant')
+                ->join('inner,inner')
+                ->on('refill_order.order_id=vr_order.order_id,refill_order.mchid=merchant.mchid')
+                ->field("refill_order.*,vr_order.order_state,({$cur_time} - refill_order.order_time - merchant.time_out) as mtime_out")
+                ->where($base_cond)
+                ->order($order_by)
                 ->select();
 
-            $relate_order_map = [];
-            foreach ($relate_list as $item) {
-                $relate_order_map[$item['order_id']] = $item['mch_order'];
-            }
-
-            $order_ids = array_column($relate_list, 'order_id');
-            $order_ids = array_unique($order_ids);
-
-            $refill_buyback_model = Model('refill_buyback');
-            $buybacks = $refill_buyback_model->getBuyBackList(['order_id' => ['in', $order_ids], 'manual_type' => 'buyback'], '', 'order_id');
-
-            $mch_order_buyback = [];
-            foreach ($buybacks as $buyback)
-            {
-                $order_id = $buyback['order_id'];
-                $relate_mch_order = $relate_order_map[$order_id];
-                if (!in_array($relate_mch_order, $mch_order_buyback)) {
-                    $mch_order_buyback[] = $relate_mch_order;
-                }
-            }
-
-            foreach ($order_list as $key => $order)
+            $merchant_list = $merchants_getter($all_mchids);
+            if(!empty($order_list))
             {
-                $mch_order = $order['mch_order'];
-                if (in_array($mch_order, $mch_order_buyback)) {
-                    $order_list[$key]['buyback'] = true;
-                } else {
-                    $order_list[$key]['buyback'] = false;
+                $order_list = $this->orderFormat($order_list, $merchant_list);
+                foreach ($order_list as $key => $item)
+                {
+                    if (in_array($item['mch_order'], $buyback_mch_orders)) {
+                        $order_list[$key]['buyback'] = true;
+                    } else {
+                        $order_list[$key]['buyback'] = false;
+                    }
                 }
             }
         }
 
+
         Tpl::output('order_list', $order_list);
         Tpl::output('merchant_list', $merchant_list);
         Tpl::output('except_stat', $this->except_stat());

+ 1 - 0
admin/language/zh_cn/core_lang_index.php

@@ -52,6 +52,7 @@ $lang['order_state_pay'] = '待发货';
 $lang['order_state_send'] = '待收货';
 $lang['order_state_success'] = '交易完成';
 $lang['order_state_eval'] = '已评价';
+$lang['order_state_buyback'] = '已返销';
 
 
 

+ 3 - 3
admin/templates/default/monitor_transfer.php

@@ -122,11 +122,11 @@
                 <td>
                     <select name="order_state" class="querySelect order_state">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="10" <?php if ($_GET['order_state'] == '10') { ?>selected<?php } ?>><?php echo $lang['order_state_new']; ?></option>
-                        <option value="20" <?php if ($_GET['order_state'] == '20') { ?>selected<?php } ?>><?php echo $lang['order_state_pay']; ?></option>
+                        <option value="-1" <?php if ($_GET['order_state'] == '-1') { ?>selected<?php } ?>><?php echo $lang['nc_all']; ?></option>
                         <option value="30" <?php if ($_GET['order_state'] == '30') { ?>selected<?php } ?>><?php echo $lang['order_state_send']; ?></option>
                         <option value="40" <?php if ($_GET['order_state'] == '40') { ?>selected<?php } ?>><?php echo $lang['order_state_success']; ?></option>
                         <option value="0" <?php if ($_GET['order_state'] == '0') { ?>selected<?php } ?>><?php echo $lang['order_state_cancel']; ?></option>
+                        <option value="-2" <?php if ($_GET['order_state'] == '-2') { ?>selected<?php } ?>><?php echo $lang['order_state_buyback']; ?></option>
                     </select>
                 </td>
 
@@ -346,7 +346,7 @@
                         <?php } ?>
                     </td>
                     <td class="align-center"><?php echo orderState($order); ?></td>
-                    <td class="align-center"><?php echo $order['buyback'] == true ? '已反销': '/';?></td>
+                    <td class="align-center"><?php echo $order['buyback'] === true ? '已反销': '/';?></td>
                     <td class="align-center"><?php echo $order['quality_text']; ?></td>
                     <td class="align-left"><?php echo $order['err_msg']; ?></td>
                     <td class="align-left"><?php echo $order['mch_order']; ?></td>

+ 1 - 1
admin/templates/default/refill_amount_stats.index.php

@@ -365,11 +365,11 @@
             <down-name-select title="机构设置" type="merchant_names"></down-name-select>
         </div>
         <div>
-            <button type="button" class="layui-btn layui-bg-blue" id="btn_refresh_approve">刷新审核</button>
             <button type="button" class="layui-btn layui-bg-blue" id="btn_search">更新数据</button>
             <button type="button" class="layui-btn layui-bg-red" id="btn_copy_data">拷贝数据</button>
             <button type="button" class="layui-btn layui-bg-red" id="btn_import">导入数据</button>
             <button type="button" class="layui-btn layui-bg-red" id="btn_copy_excel">拷贝表格</button>
+            <button type="button" class="layui-btn layui-bg-blue" id="btn_refresh_approve">刷新审核</button>
         </div>
     </div>
     <div class="layui-clear"></div>

+ 206 - 0
data/config/yl/phone.ini.php

@@ -2773,6 +2773,207 @@ $techaohe_trd_phone = [
 //        ]
     ]
 ];
+$nantai_phone = [
+    'name' => 'nantai', 'store_id' => 364, 'qualitys' => '1', 'official_sn' => true, 'refill_type' => 'api',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8930, 'price' => 10, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8930, 'price' => 10, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8930, 'price' => 10, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8931, 'price' => 20, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8931, 'price' => 20, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8931, 'price' => 20, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        30 => [
+            ['goods_id' => 8932, 'price' => 29.04, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8932, 'price' => 28.2, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8932, 'price' => 30, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        50 => [
+            ['goods_id' => 8933, 'price' => 48.4, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8933, 'price' => 47, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8933, 'price' => 48.6, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8934, 'price' => 96.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8934, 'price' => 94, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8934, 'price' => 97.2, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8935, 'price' => 193.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8935, 'price' => 188, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8935, 'price' => 194.4, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 8936, 'price' => 300, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8936, 'price' => 300, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8936, 'price' => 300, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 8937, 'price' => 500, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8937, 'price' => 500, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8937, 'price' => 500, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ]
+];
+$nantai_sec_phone = [
+    'name' => 'nantai_sec', 'store_id' => 365, 'qualitys' => '1', 'official_sn' => true, 'refill_type' => 'api',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8938, 'price' => 10, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8938, 'price' => 10, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8938, 'price' => 10, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8939, 'price' => 20, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8939, 'price' => 20, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8939, 'price' => 20, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        30 => [
+//            ['goods_id' => 8940, 'price' => 30, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8940, 'price' => 28.38, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8940, 'price' => 30, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        50 => [
+            ['goods_id' => 8941, 'price' => 48.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8941, 'price' => 47.3, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8941, 'price' => 48.6, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8942, 'price' => 97, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8942, 'price' => 94.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8942, 'price' => 97.2, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8943, 'price' => 194, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8943, 'price' => 189.2, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8943, 'price' => 194.4, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 8944, 'price' => 300, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8944, 'price' => 300, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8944, 'price' => 300, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 8945, 'price' => 500, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8945, 'price' => 500, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8945, 'price' => 500, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ]
+];
+$nantai_jingdong_phone = [
+    'name' => 'nantai_jingdong', 'store_id' => 366, 'qualitys' => '1', 'official_sn' => true, 'refill_type' => 'api',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8946, 'price' => 10, 'quality' => 1, 'card_type' => 'chinamobile'],
+//        ],
+//        20 => [
+//            ['goods_id' => 8947, 'price' => 20, 'quality' => 1, 'card_type' => 'chinamobile'],
+//        ],
+//        30 => [
+//            ['goods_id' => 8948, 'price' => 30, 'quality' => 1, 'card_type' => 'chinamobile'],
+//        ],
+        50 => [
+            ['goods_id' => 8949, 'price' => 48.4, 'quality' => 1, 'card_type' => 'chinamobile'],
+        ],
+        100 => [
+            ['goods_id' => 8950, 'price' => 96.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+        ],
+        200 => [
+            ['goods_id' => 8951, 'price' => 193.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+        ],
+//        300 => [
+//            ['goods_id' => 8952, 'price' => 300, 'quality' => 1, 'card_type' => 'chinamobile'],
+//        ],
+//        500 => [
+//            ['goods_id' => 8953, 'price' => 500, 'quality' => 1, 'card_type' => 'chinamobile'],
+//        ]
+    ]
+];
+$nantai_fs_phone = [
+    'name' => 'nantai_fs', 'store_id' => 367, 'qualitys' => '1', 'official_sn' => true, 'refill_type' => 'api',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8954, 'price' => 10, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8954, 'price' => 10, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8955, 'price' => 20, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8955, 'price' => 20, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        30 => [
+//            ['goods_id' => 8956, 'price' => 30, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8956, 'price' => 30, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        50 => [
+            ['goods_id' => 8957, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8957, 'price' => 47.5, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8958, 'price' => 95, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8958, 'price' => 95, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8959, 'price' => 190, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8959, 'price' => 190, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+//        300 => [
+//            ['goods_id' => 8960, 'price' => 300, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8960, 'price' => 300, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        500 => [
+//            ['goods_id' => 8961, 'price' => 500, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8961, 'price' => 500, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ]
+    ]
+];
+$yeyekcthreehv_phone = [
+    'name' => 'yeyekcthreehv', 'store_id' => 368, 'qualitys' => '2', 'official_sn' => true, 'refill_type' => 'api',
+    'amount' => [
+        10 => [
+            ['goods_id' => 8962, 'price' => 10, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8962, 'price' => 10, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8962, 'price' => 10, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        20 => [
+            ['goods_id' => 8963, 'price' => 20, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8963, 'price' => 20, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8963, 'price' => 20, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        30 => [
+            ['goods_id' => 8964, 'price' => 30, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8964, 'price' => 30, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8964, 'price' => 30, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        50 => [
+            ['goods_id' => 8965, 'price' => 50, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8965, 'price' => 50, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8965, 'price' => 50, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8966, 'price' => 100, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8966, 'price' => 100, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8966, 'price' => 100, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8967, 'price' => 200, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8967, 'price' => 200, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8967, 'price' => 200, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        300 => [
+            ['goods_id' => 8968, 'price' => 300, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8968, 'price' => 300, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8968, 'price' => 300, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ],
+        500 => [
+            ['goods_id' => 8969, 'price' => 500, 'quality' => 2, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8969, 'price' => 500, 'quality' => 2, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 8969, 'price' => 500, 'quality' => 2, 'card_type' => 'chinatelecom']
+        ]
+    ]
+];
 
 $phone_providers = [
 	[ 'name' => 'zhongst', 'cfg' => $zhongst_phone ],
@@ -2862,4 +3063,9 @@ $phone_providers = [
     [ 'name' => 'cuanqi_sec', 'cfg' => $cuanqi_sec_phone ],
     [ 'name' => 'tetengsu_sec', 'cfg' => $tetengsu_sec_phone ],
     [ 'name' => 'techaohe_trd', 'cfg' => $techaohe_trd_phone ],
+    [ 'name' => 'nantai', 'cfg' => $nantai_phone ],
+    [ 'name' => 'nantai_sec', 'cfg' => $nantai_sec_phone ],
+    [ 'name' => 'nantai_jingdong', 'cfg' => $nantai_jingdong_phone ],
+    [ 'name' => 'nantai_fs', 'cfg' => $nantai_fs_phone ],
+    [ 'name' => 'yeyekcthreehv', 'cfg' => $yeyekcthreehv_phone ],
 	];

+ 25 - 0
data/model/refill_buyback.model.php

@@ -22,4 +22,29 @@ class refill_buybackModel extends Model
         if (empty($order_info)) return [];
         return $order_info;
     }
+
+    public function getAllBuybackOrder($condition, $field = '*')
+    {
+        $len = 1000;
+
+        $i = 0;
+        $orders = [];
+        while (true)
+        {
+            $start = $i * $len;
+            $items = $this->table('refill_buyback,refill_order,vr_order')
+                ->on('refill_buyback.order_id=refill_order.order_id,refill_order.order_id=vr_order.order_id')
+                ->field($field)
+                ->join('inner,inner')
+                ->where($condition)
+                ->limit("{$start},{$len}")
+                ->select();
+            $orders = array_merge($orders,$items);
+            if (empty($items) || count($items) < $len) {
+                break;
+            }
+            $i++;
+        }
+        return $orders;
+    }
 }

BIN
helper/refill/api/xyz/guochuang/20250307_yd_guangdong.jpg


BIN
helper/refill/api/xyz/guochuang/20250307_yd_guangdong2.jpg


+ 39 - 0
helper/refill/api/yl/nantai/API.MD

@@ -0,0 +1,39 @@
+## 南泰全国1号
+
+### 正式环境:
+- 话费下单地址:http://8.154.19.179:16188/plat/api/hf/submitorder
+- 查询地址:http://8.154.19.179:16188/plat/api/queryorder
+- 查询余额地址:http://8.154.19.179:16188/plat/api/querybalance
+
+- 客户端地址:http://8.154.19.179:16188/plat/login
+- 账号:南泰全国1
+- 密码:nt123456
+- 客户ID:100003
+- 密钥:aa5303ead7314d2ea5f4145d908b7bfb
+
+### 对接文档地址:
+> https://docs.qq.com/doc/DWEhQWEhDVEJIdUVC
+
+### 店铺账号
+- nantai
+- nantai67890
+
+### 产品编码
+```angular2html
+全国1账户产品 移动30-200 折扣96.8
+全国移动200元 1000200
+全国移动100元 1000100
+全国移动50元 1000050
+全国移动30元 1000030
+
+全国1账户产品 联通 30-200 折扣94
+全国联通200元 2000200
+全国联通100元 2000100
+全国联通50元 2000050
+全国联通30元 2000030
+
+全国1账户产品 电信 50-200 折扣97.2
+全国电信200元 3000200
+全国电信100元 3000100
+全国电信50元 3000050
+```

+ 52 - 0
helper/refill/api/yl/nantai/RefillCallBack.php

@@ -0,0 +1,52 @@
+<?php
+namespace refill\nantai;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai/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')->getOrderInfoForNotify(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false, false, ''];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $official_sn = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+
+            $data['official_sn'] = $official_sn;
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true, $official_sn];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true, true, ''];
+        }
+        else {
+            return [$order_id, false, false, false, ''];
+        }
+    }
+}

+ 146 - 0
helper/refill/api/yl/nantai/RefillPhone.php

@@ -0,0 +1,146 @@
+<?php
+
+namespace refill\nantai;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai/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, '网络错误', ''];
+            }
+
+            $official_sn = '';
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $official_sn = $resp['szRtnMsg'];
+
+                $updata['official_sn'] = $official_sn;
+                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, $official_sn];
+        }
+    }
+
+    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);
+    }
+}

+ 47 - 0
helper/refill/api/yl/nantai/config.php

@@ -0,0 +1,47 @@
+<?php
+
+
+namespace refill\nantai;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://8.154.19.179:16188/plat/api/hf/submitorder';
+    const QUERY_URL= 'http://8.154.19.179:16188/plat/api/queryorder';
+    const BALANCE_URL = 'http://8.154.19.179:16188/plat/api/querybalance';
+
+    const USER_ID= '100003';
+    const KEY = 'aa5303ead7314d2ea5f4145d908b7bfb';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_nantai.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 => [
+            30 => 1000030,
+            50 => 1000050,
+            100 => 1000100,
+            200 => 1000200,
+        ],
+        mtopcard\ChinaUnicomCard => [
+            30  => 2000030,
+            50  => 2000050,
+            100 => 2000100,
+            200 => 2000200,
+        ],
+        mtopcard\ChinaTelecomCard => [
+            50  => 3000050,
+            100 => 3000100,
+            200 => 3000200,
+        ],
+    ];
+}

+ 64 - 0
helper/refill/api/yl/nantai_fs/API.MD

@@ -0,0 +1,64 @@
+## 晟翀分省
+
+### 正式环境:
+- 话费下单地址:http://8.154.19.179:16188/plat/api/hf/submitorder
+- 查询地址:http://8.154.19.179:16188/plat/api/queryorder
+- 查询余额地址:http://8.154.19.179:16188/plat/api/querybalance
+
+- 客户端地址:http://8.154.19.179:16188/plat/login
+- 账号:南泰分省
+- 密码:nt123456
+- 客户ID:100006
+- 密钥:a783bf4f3d9643c8ad098c566f659469
+
+### 对接文档地址:
+> https://docs.qq.com/doc/DWEhQWEhDVEJIdUVC
+
+### 店铺账号
+- nantai_fs
+- nantai_fs67890
+
+### 产品编码
+```angular2html
+分省账户产品 移动 50-200 折扣95
+陕西移动200元 1610200
+陕西移动100元 1610100
+陕西移动50元 1610050
+
+广东移动200元 1440200
+广东移动100元 1440100
+广东移动50元 1440050
+
+湖南移动200元 1430200
+湖南移动100元 1430100
+湖南移动50元 1430050
+
+江苏移动200元 1320200
+江苏移动100元 1320100
+江苏移动50元 1320050
+
+天津移动200元 1120200
+天津移动100元 1120100
+天津移动50元 1120050
+
+分省账户产品 电信 50-200 折扣95
+甘肃电信200元 3620200
+甘肃电信100元 3620100
+甘肃电信50元 3620050
+
+陕西电信200元 3610200
+陕西电信100元 3610100
+陕西电信50元 3610050
+
+广东电信200元 3440200
+广东电信100元 3440100
+广东电信50元 3440050
+
+湖南电信200元 3430200
+湖南电信100元 3430100
+湖南电信50元 3430050
+
+天津电信200元 3120200
+天津电信100元 3120100
+天津电信50元 3120050
+```

+ 52 - 0
helper/refill/api/yl/nantai_fs/RefillCallBack.php

@@ -0,0 +1,52 @@
+<?php
+namespace refill\nantai_fs;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_fs/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')->getOrderInfoForNotify(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false, false, ''];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $official_sn = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+
+            $data['official_sn'] = $official_sn;
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true, $official_sn];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true, true, ''];
+        }
+        else {
+            return [$order_id, false, false, false, ''];
+        }
+    }
+}

+ 165 - 0
helper/refill/api/yl/nantai_fs/RefillPhone.php

@@ -0,0 +1,165 @@
+<?php
+
+namespace refill\nantai_fs;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_fs/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    public function goods($quality,int $amount,int $card_type,$regin_no,$other)
+    {
+        [$goods_id, $price] = parent::goods($quality,$amount,$card_type,$regin_no,$other);
+        if($goods_id <= 0) return [0,0];
+        $key = "{$card_type}-{$amount}-{$regin_no}";
+        $price = config::Price[$key];
+        if(empty($price)) {
+            Log::record("channel cannot find price where name={$this->mName}, goods_id = {$goods_id} card_type={$card_type} amount={$amount} regin_no={$regin_no}",Log::ERR);
+            return [0,0];
+        } else {
+            return [$goods_id,ncPriceFormat($price)];
+        }
+    }
+
+    private function req_params(int $phone, int $amount, int $card_type, string $order_sn, string $regin_no)
+    {
+        $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][$regin_no][$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'];
+        $regin_no = $params['regin_no'] ?? -1;
+
+        if($regin_no <= 0) {
+            return [false, '省份获取错误', false];
+        }
+        $params = $this->req_params($card_no, $amount, $card_type, $order_sn, $regin_no);
+
+        $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, '网络错误', ''];
+            }
+
+            $official_sn = '';
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $official_sn = $resp['szRtnMsg'];
+
+                $updata['official_sn'] = $official_sn;
+                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, $official_sn];
+        }
+    }
+
+    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);
+    }
+}

+ 115 - 0
helper/refill/api/yl/nantai_fs/config.php

@@ -0,0 +1,115 @@
+<?php
+
+
+namespace refill\nantai_fs;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://8.154.19.179:16188/plat/api/hf/submitorder';
+    const QUERY_URL= 'http://8.154.19.179:16188/plat/api/queryorder';
+    const BALANCE_URL = 'http://8.154.19.179:16188/plat/api/querybalance';
+
+    const USER_ID= '100006';
+    const KEY = 'a783bf4f3d9643c8ad098c566f659469';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_nantai_fs.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 => [
+            //陕西
+            27 => [
+                50  => 1610050,
+                100 => 1610100,
+                200 => 1610200,
+            ],
+            //广东
+            19 => [
+                50  => 1440050,
+                100 => 1440100,
+                200 => 1440200,
+            ],
+            //湖南
+            18 => [
+                50  => 1430050,
+                100 => 1430100,
+                200 => 1430200,
+            ],
+            //江苏
+            10 => [
+                50  => 1320050,
+                100 => 1320100,
+                200 => 1320200,
+            ],
+            //天津
+            2 => [
+                50  => 1120050,
+                100 => 1120100,
+                200 => 1120200,
+            ],
+
+        ],
+        mtopcard\ChinaUnicomCard => [
+
+        ],
+        mtopcard\ChinaTelecomCard => [
+            //甘肃
+            28 => [
+                50  => 3620050,
+                100 => 3620100,
+                200 => 3620200,
+            ],
+            //陕西
+            27 => [
+                50  => 3610050,
+                100 => 3610100,
+                200 => 3610200,
+            ],
+            //广东
+            19 => [
+                50  => 3440050,
+                100 => 3440100,
+                200 => 3440200,
+            ],
+            //湖南
+            18 => [
+                50  => 3430050,
+                100 => 3430100,
+                200 => 3430200,
+            ],
+            //天津
+            2 => [
+                50  => 3120050,
+                100 => 3120100,
+                200 => 3120200,
+            ],
+        ]
+    ];
+
+    //key格式 卡类型-面值-regin_no
+    const Price = [
+        //移动
+        "4-50-27" => 47.5, "4-100-27" => 95, "4-200-27" => 190, //陕西
+        "4-50-19" => 47.5, "4-100-19" => 95, "4-200-19" => 190, //广东
+        "4-50-18" => 47.5, "4-100-18" => 95, "4-200-18" => 190, //湖南
+        "4-50-10" => 47.5, "4-100-10" => 95, "4-200-10" => 190, //江苏
+        "4-50-2" => 47.5, "4-100-2" => 95, "4-200-2" => 190, //天津
+
+        //电信
+        "6-50-28" => 47.5, "6-100-28" => 95, "6-200-28" => 190, //甘肃
+        "6-50-27" => 47.5, "6-100-27" => 95, "6-200-27" => 190, //陕西
+        "6-50-19" => 47.5, "6-100-19" => 95, "6-200-19" => 190, //广东
+        "6-50-18" => 47.5, "6-100-18" => 95, "6-200-18" => 190, //湖南
+        "6-50-2" => 47.5, "6-100-2" => 95, "6-200-2" => 190, //天津
+    ];
+}

+ 27 - 0
helper/refill/api/yl/nantai_jingdong/API.MD

@@ -0,0 +1,27 @@
+## 南泰京东
+
+### 正式环境:
+- 话费下单地址:http://8.154.19.179:16188/plat/api/hf/submitorder
+- 查询地址:http://8.154.19.179:16188/plat/api/queryorder
+- 查询余额地址:http://8.154.19.179:16188/plat/api/querybalance
+
+- 客户端地址:http://8.154.19.179:16188/plat/login
+- 账号:南泰京东
+- 密码:nt123456
+- 客户ID:100005
+- 密钥:8a7df5c90c4948fa870316a844c19f21
+
+### 对接文档地址:
+> https://docs.qq.com/doc/DWEhQWEhDVEJIdUVC
+
+### 店铺账号
+- nantai_jingdong
+- nantai_jingdong67890
+
+### 产品编码
+```angular2html
+南泰京东账户 产品 移动 50-200 折扣96.8
+全国移动200元 1000200
+全国移动100元 1000100
+全国移动50元 1000050
+```

+ 52 - 0
helper/refill/api/yl/nantai_jingdong/RefillCallBack.php

@@ -0,0 +1,52 @@
+<?php
+namespace refill\nantai_jingdong;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_jingdong/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')->getOrderInfoForNotify(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false, false, ''];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $official_sn = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+
+            $data['official_sn'] = $official_sn;
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true, $official_sn];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true, true, ''];
+        }
+        else {
+            return [$order_id, false, false, false, ''];
+        }
+    }
+}

+ 146 - 0
helper/refill/api/yl/nantai_jingdong/RefillPhone.php

@@ -0,0 +1,146 @@
+<?php
+
+namespace refill\nantai_jingdong;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_jingdong/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, '网络错误', ''];
+            }
+
+            $official_sn = '';
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $official_sn = $resp['szRtnMsg'];
+
+                $updata['official_sn'] = $official_sn;
+                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, $official_sn];
+        }
+    }
+
+    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);
+    }
+}

+ 41 - 0
helper/refill/api/yl/nantai_jingdong/config.php

@@ -0,0 +1,41 @@
+<?php
+
+
+namespace refill\nantai_jingdong;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://8.154.19.179:16188/plat/api/hf/submitorder';
+    const QUERY_URL= 'http://8.154.19.179:16188/plat/api/queryorder';
+    const BALANCE_URL = 'http://8.154.19.179:16188/plat/api/querybalance';
+
+    const USER_ID= '100005';
+    const KEY = '8a7df5c90c4948fa870316a844c19f21';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_nantai_jingdong.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,
+        ],
+        mtopcard\ChinaUnicomCard => [
+
+        ],
+        mtopcard\ChinaTelecomCard => [
+
+        ],
+    ];
+}

+ 38 - 0
helper/refill/api/yl/nantai_sec/API.MD

@@ -0,0 +1,38 @@
+## 南泰全国2号
+
+### 正式环境:
+- 话费下单地址:http://8.154.19.179:16188/plat/api/hf/submitorder
+- 查询地址:http://8.154.19.179:16188/plat/api/queryorder
+- 查询余额地址:http://8.154.19.179:16188/plat/api/querybalance
+
+- 客户端地址:http://8.154.19.179:16188/plat/login
+- 账号:南泰全国2
+- 密码:nt123456
+- 客户ID:100004
+- 密钥:9dcb870c4fa74dc4abbaf9152c572c5a
+
+### 对接文档地址:
+> https://docs.qq.com/doc/DWEhQWEhDVEJIdUVC
+
+### 店铺账号
+- nantai_sec
+- nantai_sec67890
+
+### 产品编码
+```angular2html
+全国2账户产品 移动50-200 折扣97
+全国移动200元 1000200
+全国移动100元 1000100
+全国移动50元 1000050
+
+全国2账户 联通30-200 折扣94.6
+全国联通200元 2000200
+全国联通100元 2000100
+全国联通50元 2000050
+全国联通30元 2000030
+
+全国2账户产品 电信50-200 折扣97.2
+全国电信200元 3000200
+全国电信100元 3000100
+全国电信50元 3000050
+```

+ 52 - 0
helper/refill/api/yl/nantai_sec/RefillCallBack.php

@@ -0,0 +1,52 @@
+<?php
+namespace refill\nantai_sec;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_sec/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')->getOrderInfoForNotify(['order_sn' => $order_sn]);
+        if (empty($order_info)) {
+            return [false, false, false, false, ''];
+        }
+        $order_id = $order_info['order_id'];
+
+        if ($status === 2) {
+            $official_sn = strtolower($params['szRtnMsg']) == 'null' ? '' : $params['szRtnMsg'];
+
+            $data['official_sn'] = $official_sn;
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true, $official_sn];
+        }
+        elseif ($status === 3) {
+            return [$order_id, false, true, true, ''];
+        }
+        else {
+            return [$order_id, false, false, false, ''];
+        }
+    }
+}

+ 146 - 0
helper/refill/api/yl/nantai_sec/RefillPhone.php

@@ -0,0 +1,146 @@
+<?php
+
+namespace refill\nantai_sec;
+
+require_once(BASE_HELPER_RAPI_PATH . '/nantai_sec/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, '网络错误', ''];
+            }
+
+            $official_sn = '';
+
+            $status = $resp['nRtn'];
+            if ($status === 5012) {
+                $official_sn = $resp['szRtnMsg'];
+
+                $updata['official_sn'] = $official_sn;
+                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, $official_sn];
+        }
+    }
+
+    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);
+    }
+}

+ 46 - 0
helper/refill/api/yl/nantai_sec/config.php

@@ -0,0 +1,46 @@
+<?php
+
+
+namespace refill\nantai_sec;
+
+use mtopcard;
+class config
+{
+    const ORDER_URL = 'http://8.154.19.179:16188/plat/api/hf/submitorder';
+    const QUERY_URL= 'http://8.154.19.179:16188/plat/api/queryorder';
+    const BALANCE_URL = 'http://8.154.19.179:16188/plat/api/querybalance';
+
+    const USER_ID= '100004';
+    const KEY = '9dcb870c4fa74dc4abbaf9152c572c5a';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_nantai_sec.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,
+        ],
+        mtopcard\ChinaUnicomCard => [
+            30  => 2000030,
+            50  => 2000050,
+            100 => 2000100,
+            200 => 2000200,
+        ],
+        mtopcard\ChinaTelecomCard => [
+            50  => 3000050,
+            100 => 3000100,
+            200 => 3000200,
+        ],
+    ];
+}

+ 14 - 0
helper/refill/api/yl/yeyekcthreehv/API.MD

@@ -0,0 +1,14 @@
+### 椰椰快充3号
+- 后台地址:https://admin.xyzshops.cn/merchant/#/login
+
+### 机构账号
+- yeyekcthreehv
+- cdf_oi3
+- 10553
+
+### 店铺账号
+- yeyekcthreehv
+- yeyekcthreehv67890
+- 
+### 密钥
+1c4a1fde01f5670e6d6bf5658bfb312f

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

@@ -0,0 +1,76 @@
+<?php
+namespace refill\yeyekcthreehv;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yeyekcthreehv/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): bool
+    {
+        if (!isset($value))
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    private function sign($params): string
+    {
+        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): array
+    {
+        $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, ''];
+        }
+        $official_sn = strtolower($params['official_sn']) == 'null' ? '' : $params['official_sn'];
+
+        $order_id = $order_info['order_id'];
+        if ($status === 'SUCCESS') {
+            $data['ch_trade_no'] = $params['trade_no'];
+            $data['official_sn'] = $official_sn;
+            Model('refill_order')->edit($order_id, $data);
+            return [$order_id, true, false, true, $official_sn];
+        }
+        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, ''];
+        }
+    }
+}

+ 161 - 0
helper/refill/api/yl/yeyekcthreehv/RefillPhone.php

@@ -0,0 +1,161 @@
+<?php
+
+namespace refill\yeyekcthreehv;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yeyekcthreehv/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): array
+    {
+        $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): array
+    {
+        $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): array
+    {
+        $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)
+            {
+                $official_sn = strtolower($resp['official_sn']) == 'null' ? '' : $resp['official_sn'];
+
+                $data = $resp['datas'];
+                if ($data['order_state'] == '40') {
+                    $save['ch_trade_no'] = $data['trade_no'];
+                    $save['official_sn'] = $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, $official_sn];
+            }
+            elseif ($resp['code'] === 202 && (time() - $refill_info['commit_time'] >= 600))
+            {
+                return [true, ORDER_STATE_NOEXIST, ''];
+            }
+            else
+            {
+                return [false, $resp['message'], ''];
+            }
+        }
+    }
+
+    public function balance(): array
+    {
+        $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, ncPriceFormat($resp['datas']['balance'])];
+            } else {
+                return [false, $resp['message']];
+            }
+        }
+    }
+
+    protected function check_empty($value): bool
+    {
+        if (!isset($value))
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    private function sign($params): string
+    {
+        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);
+    }
+}

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

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

+ 4 - 0
mobile/callback/refill_nantai.php

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

+ 4 - 0
mobile/callback/refill_nantai_fs.php

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

+ 4 - 0
mobile/callback/refill_nantai_jingdong.php

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

+ 4 - 0
mobile/callback/refill_nantai_sec.php

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

+ 4 - 0
mobile/callback/refill_yeyekcthreehv.php

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

+ 30 - 0
test/TestRefill.php

@@ -6515,6 +6515,36 @@ class TestRefill extends TestCase
         $provider = $this->getProvider('techaohe_trd');
         $resp = $provider->balance();
     }
+
+    public function testnantai()
+    {
+        $provider = $this->getProvider('nantai');
+        $resp = $provider->balance();
+    }
+
+    public function testnantai_sec()
+    {
+        $provider = $this->getProvider('nantai_sec');
+        $resp = $provider->balance();
+    }
+
+    public function testnantai_jingdong()
+    {
+        $provider = $this->getProvider('nantai_jingdong');
+        $resp = $provider->balance();
+    }
+
+    public function testnantai_fs()
+    {
+        $provider = $this->getProvider('nantai_fs');
+        $resp = $provider->balance();
+    }
+
+    public function testyeyekcthreehv()
+    {
+        $provider = $this->getProvider('yeyekcthreehv');
+        $resp = $provider->balance();
+    }
 }
 
 

+ 118 - 0
test/TestTransferOrder.php

@@ -0,0 +1,118 @@
+<?php
+
+
+use PHPUnit\Framework\TestCase;
+use const mtopcard\ProvinceList;
+
+define('APP_ID', 'test');
+define('BASE_ROOT_PATH', str_replace('/test', '', dirname(__FILE__)));
+define('BASE_HELPER_PATH', BASE_ROOT_PATH . '/helper');
+
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_CORE_PATH . '/lrlz.php');
+require_once(BASE_HELPER_PATH . '/task/manager.php');
+require_once(BASE_HELPER_PATH . '/task/handler.php');
+require_once(BASE_HELPER_PATH . '/task/task_wrapper.php');
+
+const CurrentTest = NetTest;
+
+class TestTransferOrder extends TestCase
+{
+
+    public static function setUpBeforeClass(): void
+    {
+        Base::run_util();
+    }
+
+    public function testSql()
+    {
+//        SELECT refill_order.*, vr_order.order_state, (1741162635 - refill_order.order_time - merchant.time_out) as mtime_out
+//        FROM `lrlz_refill_order` AS `refill_order`
+//                 INNER JOIN `lrlz_vr_order` AS `vr_order` ON refill_order.order_id = vr_order.order_id
+//                 INNER JOIN `lrlz_merchant` AS `merchant` ON refill_order.mchid = merchant.mchid
+//        WHERE (refill_order.inner_status = 0)
+//        AND (refill_order.mchid IN (10296, 10292, 10297, 10549, 10550))
+//          AND (refill_order.order_time >= 1741017600)
+//            and (vr_order.order_state in (30,0))
+//          and refill_order.is_retrying = 0
+//        # and (refill_order.order_sn='2216470794433302240785')
+//            AND NOT EXISTS (
+//                SELECT 1
+//                FROM lrlz_refill_order AS ro
+//                INNER JOIN lrlz_vr_order vo
+//                    ON ro.order_id=vo.order_id
+//                INNER JOIN lrlz_refill_buyback AS rb
+//                    ON ro.order_id = rb.order_id
+//                WHERE  ro.order_time >= 1741017600 and ro.mch_order = refill_order.mch_order  and vo.order_state=40
+//            )
+//        ORDER BY refill_order.order_time desc
+//        LIMIT 1000;
+
+//        SELECT
+//             refill_order.order_id,
+//             refill_order.order_sn,
+//             refill_order.mchid,
+//             refill_order.mch_order,
+//             refill_order.card_no,
+//            vr_order.order_state,
+//            (UNIX_TIMESTAMP() - refill_order.order_time - merchant.time_out) AS mtime_out,
+//            MAX(refill_order.order_time) AS max_order_time -- 选取最大 order_time
+//        FROM `lrlz_refill_order` AS `refill_order`
+//        INNER JOIN `lrlz_vr_order` AS `vr_order`
+//            ON refill_order.order_id = vr_order.order_id
+//        INNER JOIN `lrlz_merchant` AS `merchant`
+//            ON refill_order.mchid = merchant.mchid
+//        LEFT JOIN `lrlz_refill_order` AS ro
+//            ON refill_order.mch_order = ro.mch_order
+//            AND ro.order_time >= 1741017600
+//        LEFT JOIN `lrlz_vr_order` AS vo
+//            ON ro.order_id = vo.order_id
+//            AND vo.order_state = 40
+//        LEFT JOIN `lrlz_refill_buyback` AS rb
+//            ON ro.order_id = rb.order_id
+//        WHERE
+//            refill_order.inner_status = 0
+//            AND refill_order.mchid IN (10296, 10292, 10297, 10549, 10550)
+//            AND refill_order.order_time >= 1741017600
+//            AND vr_order.order_state IN (30, 0)
+//            AND refill_order.is_retrying = 0
+//        GROUP BY refill_order.order_id, refill_order.mch_order, refill_order.mchid, refill_order.card_no, vr_order.order_state,refill_order.order_sn, refill_order.order_time, merchant.time_out
+//        HAVING COUNT(DISTINCT CASE WHEN rb.order_id IS NOT NULL THEN ro.order_id END) = 0
+//        ORDER BY max_order_time DESC
+//        LIMIT 1000;
+
+        $con = [
+            'refill_buyback.order_time' => ['egt', 1740758400],
+            'refill_order.order_time' => ['egt', 1740758400],
+            'vr_order.order_state' => ORDER_STATE_SUCCESS
+        ];
+        $res = $this->getAllBuybackOrder($con);
+    }
+
+    public function getAllBuybackOrder($condition)
+    {
+        $model = Model('');
+
+        $len = 1000;
+
+        $i = 0;
+        $orders = [];
+        while (true)
+        {
+            $start = $i * $len;
+            $items = $model->table('refill_buyback,refill_order,vr_order')
+                ->on('refill_buyback.order_id=refill_order.order_id,refill_order.order_id=vr_order.order_id')
+                ->field("distinct refill_order.mch_order")
+                ->join('inner,inner')
+                ->where($condition)
+                ->limit("{$start},{$len}")
+                ->select();
+            $orders = array_merge($orders,$items);
+            if (empty($items) || count($items) < $len) {
+                break;
+            }
+            $i++;
+        }
+        return $orders;
+    }
+}