Browse Source

Merge branch 'raccount' into rprofit

stanley-king 2 years ago
parent
commit
b0a13f95e5
71 changed files with 3272 additions and 163 deletions
  1. 4 1
      admin/control/refill_merchant_channel_cfg.php
  2. 34 0
      admin/control/retail.php
  3. 4 2
      admin/include/limit.php
  4. 67 46
      admin/include/menu.php
  5. 9 9
      admin/templates/default/refill.merchant.channel.cfg.php
  6. 242 0
      admin/templates/default/retail.list.php
  7. 162 24
      data/config/xyz/refill.ini.php
  8. 117 24
      data/config/yl/refill.ini.php
  9. 27 0
      data/model/retail.model.php
  10. 1 0
      docker/compose/xiaoyu/admin/docker-compose.yml
  11. 50 0
      helper/refill/api/xyz/dazhanggui_high/RefillCallBack.php
  12. 142 0
      helper/refill/api/xyz/dazhanggui_high/RefillPhone.php
  13. 15 0
      helper/refill/api/xyz/dazhanggui_high/api.txt
  14. 35 0
      helper/refill/api/xyz/dazhanggui_high/config.php
  15. BIN
      helper/refill/api/xyz/guochuang/20220916辽宁青海移动调价函.jpg
  16. 2 2
      helper/refill/api/xyz/guochuang/config.php
  17. BIN
      helper/refill/api/xyz/tianyi/800系统接口文档/【1.优先详看】天翼流量800新接口协议(2021.11).pdf
  18. 187 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/C#加密模版.txt
  19. 424 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/C++ AES加密模板.txt
  20. 115 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/Java AES加密模板.java
  21. 54 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/php AES加密模板.php
  22. 70 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/python AES加密模板.py
  23. 54 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/c#回调解密.txt
  24. 10 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/java回调解密.txt
  25. 24 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/php回调示例.txt
  26. 128 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【3】回调Demo(明文)/.net&C#回调示例.txt
  27. 42 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【3】回调Demo(明文)/java回调示例.txt
  28. 48 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【4】签名校验模板及公钥/Java DSA校验模板.java
  29. 7 0
      helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【4】签名校验模板及公钥/回调参数签名校验公钥.txt
  30. BIN
      helper/refill/api/xyz/tianyi/800系统接口文档/【3.申请参数用】BMS合同参数配置申请操作指引.pdf
  31. BIN
      helper/refill/api/xyz/tianyi/800系统接口文档/【4.测试订购失败时看】合作方接口联调常见问题处理指引-2018.7.xlsx
  32. 13 0
      helper/refill/api/xyz/tianyi/800系统接口文档/平台下单地址及出口IP.txt
  33. BIN
      helper/refill/api/xyz/tianyi/800系统接口文档/综合平台订购接口错误编码表及处理建议_2021.11.xlsx
  34. 68 0
      helper/refill/api/xyz/tianyi/RefillCallBack.php
  35. 166 0
      helper/refill/api/xyz/tianyi/RefillPhone.php
  36. 6 0
      helper/refill/api/xyz/tianyi/account.txt
  37. 68 0
      helper/refill/api/xyz/tianyi/config.php
  38. BIN
      helper/refill/api/xyz/tianyi/北京趣带娃科技有限公司正式合同参数.xlsx
  39. 3 1
      helper/refill/api/xyz/weixue/config.php
  40. 4 0
      helper/refill/api/xyz/weixue/对接文档-yezi.txt
  41. 4 2
      helper/refill/api/xyz/xinruiheng/config.php
  42. 5 1
      helper/refill/api/xyz/xinruiheng/对接文档-yezi.txt
  43. 4 3
      helper/refill/api/xyz/yelin_hf/RefillCallBack.php
  44. 3 2
      helper/refill/api/xyz/yelin_hf/RefillPhone.php
  45. 55 0
      helper/refill/api/xyz/yingdian_hf/RefillCallBack.php
  46. 140 0
      helper/refill/api/xyz/yingdian_hf/RefillPhone.php
  47. 16 0
      helper/refill/api/xyz/yingdian_hf/config.php
  48. 3 0
      helper/refill/api/xyz/yingdian_hf/对接文档.txt
  49. 50 0
      helper/refill/api/yl/dazhanggui_high/RefillCallBack.php
  50. 142 0
      helper/refill/api/yl/dazhanggui_high/RefillPhone.php
  51. 15 0
      helper/refill/api/yl/dazhanggui_high/api.txt
  52. 35 0
      helper/refill/api/yl/dazhanggui_high/config.php
  53. 2 2
      helper/refill/api/yl/guochuang/config.php
  54. 2 0
      helper/refill/api/yl/weixue/config.php
  55. 4 2
      helper/refill/api/yl/xinruiheng/config.php
  56. 55 0
      helper/refill/api/yl/yingdian_hf/RefillCallBack.php
  57. 140 0
      helper/refill/api/yl/yingdian_hf/RefillPhone.php
  58. 16 0
      helper/refill/api/yl/yingdian_hf/config.php
  59. 3 0
      helper/refill/api/yl/yingdian_hf/对接文档.txt
  60. 4 0
      mobile/callback/refill_dazhanggui_high.php
  61. 4 0
      mobile/callback/refill_yingdian_hf.php
  62. 2 1
      plot/refill/ChannelCovSuccPainter.py
  63. 2 1
      plot/refill/ChannelPainter.py
  64. 15 14
      plot/refill/MerchantAmountPainter.py
  65. 15 1
      plot/refill/MerchantPainter.py
  66. 2 1
      plot/refill/NetcheckPainter.py
  67. 30 22
      rdispatcher/proxy.php
  68. 28 0
      test/TestRefill.php
  69. 12 0
      test/TestRefillYl.php
  70. 11 2
      vapi/control/retail.php
  71. 51 0
      vapi/control/sapi.php

+ 4 - 1
admin/control/refill_merchant_channel_cfg.php

@@ -16,6 +16,9 @@ class refill_merchant_channel_cfgControl extends SystemControl
         $cache_field = "{$type}-{$quality}";
 
         $merchants = $this->merchants(['merchant_state' => 1], 'merchant_state asc, company_name asc');
+        foreach ($merchants as $key => $merchant) {
+            $merchants[$key]['time_out_text'] = $this->elapse_time($merchant['time_out']);
+        }
         $cond = ['type' => $type, 'qualitys' => ['like', '%' . $quality . '%'], 'opened' => 1];
         $open_providers = $this->providers($cond);
 
@@ -85,4 +88,4 @@ class refill_merchant_channel_cfgControl extends SystemControl
             wcache('merchant_channel-cfg', [$cache_field => $val], 'refill-');
         }
     }
-}
+}

+ 34 - 0
admin/control/retail.php

@@ -0,0 +1,34 @@
+<?php
+
+class retailControl extends SystemControl
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function indexOp()
+    {
+        $retail_mod = Model('retail');
+        $cond = [];
+        $_GET['state'] = $_GET['state'] ?? '0';
+        if(in_array($_GET['state'], [ '0', '1'])) {
+            $cond['state'] = $_GET['state'];
+        }
+        $retail_list = $retail_mod->getList($cond, 200);
+
+        Tpl::output('list', $retail_list);
+        Tpl::output('state_text', ['未提交','已提交']);
+        Tpl::output('page', $retail_mod->showpage());
+        Tpl::showpage('retail.list');
+    }
+
+    public function retail_disposeOp()
+    {
+        $retail_mod = Model('retail');
+        $id = $_GET['id'];
+        $cond['retail_id'] = ['in',$id];
+        $retail_mod->dispose_commit($cond);
+        showMessage('操作成功','index.php?act=retail&op=index');
+    }
+}

+ 4 - 2
admin/include/limit.php

@@ -2,7 +2,7 @@
 /**
  * 载入权限
  *
- 
+
  */
 defined('InShopNC') or exit('Access Invalid!');
 $_limit =  array(
@@ -55,7 +55,9 @@ $_limit =  array(
         array('name'=> '任务列表', 'op'=>null, 'act'=>'task'),
         array('name'=> '异常订单列表', 'op'=>null, 'act'=>'refill_error'),
         array('name'=> '服务器磁盘监控', 'op'=>null, 'act'=>'arw_monitor'),
-
+    )),
+    array('name' => '办卡业务', 'child' => array(
+        array('name' => '信息列表', 'op' => null, 'act' => 'retail'),
     )),
 	array('name'=>$lang['nc_store'], 'child'=>array(
 		array('name'=>$lang['nc_store_manage'], 'op'=>null, 'act'=>'store'),

+ 67 - 46
admin/include/menu.php

@@ -2,7 +2,7 @@
 /**
  * 菜单
  *
- 
+
  */
 defined('InShopNC') or exit('Access Invalid!');
 /**
@@ -11,39 +11,53 @@ defined('InShopNC') or exit('Access Invalid!');
  */
 $arr = array(
 		'top' => array(
-			0 => array(
+			[
 				'args' 	=> 'dashboard',
-				'text' 	=> $lang['nc_console']),
-			1 => array(
+				'text' 	=> $lang['nc_console']
+			],
+			[
 				'args' 	=> 'setting',
-				'text' 	=> $lang['nc_config']),
-			2 => array(
+				'text' 	=> $lang['nc_config']
+			],
+			[
 				'args' 	=> 'goods',
-				'text' 	=> $lang['nc_goods']),
-			3 => array(
+				'text' 	=> $lang['nc_goods']
+			],
+			[
 				'args' 	=> 'merchant',
-				'text' 	=> '充值业务'),
-			4 => array(
+				'text' 	=> '充值业务'
+			],
+			[
+				'args' 	=> 'card',
+				'text' 	=> '办卡业务'
+			],
+			[
 				'args' 	=> 'store',
-				'text' 	=> $lang['nc_store']),
-			5 => array(
+				'text' 	=> $lang['nc_store']
+			],
+			[
 				'args'	=> 'member',
-				'text'	=> $lang['nc_member']),
-			6 => array(
+				'text'	=> $lang['nc_member']
+			],
+			[
 				'args' 	=> 'trade',
-				'text'	=> $lang['nc_trade']),
-			7 => array(
+				'text'	=> $lang['nc_trade']
+			],
+			[
 				'args'	=> 'website',
-				'text' 	=> $lang['nc_website']),
-			8 => array(
+				'text' 	=> $lang['nc_website']
+			],
+			[
 				'args'	=> 'operation',
-				'text'	=> $lang['nc_operation']),
-			9 => array(
+				'text'	=> $lang['nc_operation']
+			],
+			[
 				'args'	=> 'stat',
-				'text'	=> $lang['nc_stat']),
+				'text'	=> $lang['nc_stat']
+			],
 		),
 		'left' =>array(
-			0 => array(
+			[
 				'nav' => 'dashboard',
 				'text' => $lang['nc_normal_handle'],
 				'list' => array(
@@ -55,8 +69,8 @@ $arr = array(
 					array('args'=>'goods,goods,dashboard',					'text'=>$lang['nc_goods_manage']),
 					array('args'=>'index,order,dashboard',			        'text'=>$lang['nc_order_manage']),
 				)
-			),
-			1 => array(
+			],
+			[
 				'nav' => 'setting',
 				'text' => $lang['nc_config'],
 				'list' => array(
@@ -76,8 +90,8 @@ $arr = array(
 					array('args'=>'search,search,setting',			'text'=>$lang['nc_admin_search_set']),
 					array('args'=>'list,admin_log,setting',			'text'=>$lang['nc_admin_log']),
 				)
-			),
-			2 => array(
+			],
+			[
 				'nav' => 'goods',
 				'text' => $lang['nc_goods'],
 				'list' => array(
@@ -88,8 +102,8 @@ $arr = array(
 					array('args'=>'spec,spec,goods',						'text'=>$lang['nc_spec_manage']),
 					array('args'=>'list,goods_album,goods',					'text'=>$lang['nc_album_manage']),
 				)
-			),
-			3 => array(
+			],
+			[
 				'nav' => 'merchant',
 				'text' => '充值业务',
 				'list' => array(
@@ -120,8 +134,15 @@ $arr = array(
 					array('args'=>'index,refill_error,merchant',			'text'=>'异常订单列表'),
 					array('args'=>'index,arw_monitor,merchant',			'text'=>'服务器磁盘监控'),
 				)
-			),
-			4 => array(
+			],
+			[
+				'nav' => 'card',
+				'text' => '办卡业务',
+				'list' => array(
+					array('args'=>'index,retail,card',			'text'=> '信息列表'),
+				)
+			],
+			[
 				'nav' => 'store',
 				'text' => $lang['nc_store'],
 				'list' => array(
@@ -134,8 +155,8 @@ $arr = array(
 					array('args'=>'edit_info,store_joinin,store',			'text'=>'开店首页'),
 					array('args'=>'list,ownshop,store',						'text'=>'自营店铺'),
 				)
-			),
-			5 => array(
+			],
+			[
 				'nav' => 'member',
 				'text' => $lang['nc_member'],
 				'list' => array(
@@ -152,8 +173,8 @@ $arr = array(
 					array('args'=>'member_tag,sns_member,member',			'text'=>$lang['nc_member_tag']),
 					array('args'=>'chat_log,chat_log,member',				'text'=>'聊天记录')
 				)
-			),
-			6 => array(
+			],
+			[
 				'nav' => 'trade',
 				'text' => $lang['nc_trade'],
 				'list' => array(
@@ -168,8 +189,8 @@ $arr = array(
 					array('args'=>'complain_new_list,complain,trade',		'text'=>$lang['nc_complain_config']),
 					array('args'=>'index,tools,trade',						'text'=>$lang['tools'])
 				)
-			),
-			7 => array(
+			],
+			[
 				'nav' => 'website',
 				'text' => $lang['nc_website'],
 				'list' => array(
@@ -182,14 +203,14 @@ $arr = array(
 					array('args'=>'rec_list,rec_position,website',			'text'=>$lang['nc_admin_res_position']),
 					array('args'=>'link,link,website',						'text'=>'友情连接'),
 				)
-			),
-			8 => array(
+			],
+			[
 				'nav' => 'operation',
 				'text' => $lang['nc_operation'],
 				'list' => array(
 					array('args'=>'setting,operation,operation',			    'text'=>$lang['nc_operation_set']),
 					array('args'=>'groupbuy_template_list,groupbuy,operation',	'text'=>$lang['nc_groupbuy_manage']),
-                    array('args'=>'index,vr_groupbuy,operation',               	'text'=>'虚拟抢购设置'),
+					array('args'=>'index,vr_groupbuy,operation',               	'text'=>'虚拟抢购设置'),
 					array('args'=>'xianshi_apply,promotion_xianshi,operation',	'text'=>$lang['nc_promotion_xianshi']),
 					array('args'=>'mansong_apply,promotion_mansong,operation',	'text'=>$lang['nc_promotion_mansong']),
 					array('args'=>'bundling_list,promotion_bundling,operation',	'text'=>$lang['nc_promotion_bundling']),
@@ -201,18 +222,18 @@ $arr = array(
 					array('args'=>'activity,activity,operation',				'text'=>$lang['nc_activity_manage']),
 					array('args'=>'pointprod,pointprod,operation',				'text'=>$lang['nc_pointprod']),
 					array('args'=>'index,mall_consult,operation',               'text'=>'平台客服'),
-                    array('args'=>'index,rechargecard,operation',               'text'=>'平台充值卡'),
-                    array('args'=>'index,delivery,operation',                   'text'=>'物流自提服务站'),
+					array('args'=>'index,rechargecard,operation',               'text'=>'平台充值卡'),
+					array('args'=>'index,delivery,operation',                   'text'=>'物流自提服务站'),
 					array('args'=>'index,oper_sms,operation',                   'text'=>$lang['oper_sms'])
 				)
-			),
-			9 => array(
+			],
+			[
 				'nav' => 'stat',
 				'text' => $lang['nc_stat'],
 				'list' => array(
-			        array('args'=>'general,stat_general,stat',			'text'=>$lang['nc_statgeneral']),
+					array('args'=>'general,stat_general,stat',			'text'=>$lang['nc_statgeneral']),
 					array('args'=>'scale,stat_industry,stat',			'text'=>$lang['nc_statindustry']),
-			        array('args'=>'newmember,stat_member,stat',			'text'=>$lang['nc_statmember']),
+					array('args'=>'newmember,stat_member,stat',			'text'=>$lang['nc_statmember']),
 					array('args'=>'newstore,stat_store,stat',			'text'=>$lang['nc_statstore']),
 					array('args'=>'income,stat_trade,stat',				'text'=>$lang['nc_stattrade']),
 					array('args'=>'pricerange,stat_goods,stat',			'text'=>$lang['nc_statgoods']),
@@ -222,7 +243,7 @@ $arr = array(
 					array('args'=>'index,stat_bonus,stat',		    	'text'=>$lang['nc_bonus_statistics']),
 					array('args'=>'index,stat_daily,stat',		    	'text'=>$lang['nc_daily_statistics']),
 				)
-			),
+			],
 		),
 );
 if(C('flea_isuse')==1){

+ 9 - 9
admin/templates/default/refill.merchant.channel.cfg.php

@@ -204,7 +204,7 @@
                             </tr>
                             <?php foreach ($output['merchant_list'] as $k => $merchant) { ?>
                                 <tr class="w500 trFlex">
-                                    <td style="width: 130px;min-width:130px;white-space: nowrap;display: flex;align-items: center;" class="tbFlex">
+                                    <td style="white-space: nowrap;display: flex;align-items: center;" class="tbFlex">
                                         <input type="checkbox" class="checkAllRow" />
                                         <?php if ($merchant['merchant_state'] == 1) { ?>
                                             <span style="color: #48975A">
@@ -212,17 +212,17 @@
                                                 <span style="color: #E53737">
                                                 <?php } ?>
 
-                                                <?php echo $merchant['company_name'] ?? $merchant['name']; ?></span>
+                                                <?php echo $merchant['company_name'] ?? $merchant['name']; ?>
+                                                <?php echo "({$merchant['time_out_text']})秒"; ?>
+                                                </span>
                                     </td>
                                     <?php foreach ($output['provider_list'] as $provider) { ?>
                                         <td class="batch-td">
-                                            <input type="checkbox" class="cellCheckBox cellCheckBox-<?php echo $k ?>" id="checkBoxList"
-                                           name="items[<?php echo $merchant['mchid'] ?>][]" value="<?php echo "{$provider['provider_id']}-{$provider['name']}"; ?>"
-                                                <?php
-                                                    if (!empty($output['merchant_channel_cfg']) && array_key_exists($merchant['mchid'], $output['merchant_channel_cfg']) && in_array($provider['provider_id'], $output['merchant_channel_cfg'][$merchant['mchid']])) {
-                                                        echo 'checked';
-                                                    }
-                                                ?>>
+                                            <input type="checkbox" class="cellCheckBox cellCheckBox-<?php echo $k ?>" id="checkBoxList" name="items[<?php echo $merchant['mchid'] ?>][]" value="<?php echo "{$provider['provider_id']}-{$provider['name']}"; ?>" <?php
+                                                                                                                                                                                                                                                                    if (!empty($output['merchant_channel_cfg']) && array_key_exists($merchant['mchid'], $output['merchant_channel_cfg']) && in_array($provider['provider_id'], $output['merchant_channel_cfg'][$merchant['mchid']])) {
+                                                                                                                                                                                                                                                                        echo 'checked';
+                                                                                                                                                                                                                                                                    }
+                                                                                                                                                                                                                                                                    ?>>
                                         </td>
                                     <?php } ?>
                                 </tr>

+ 242 - 0
admin/templates/default/retail.list.php

@@ -0,0 +1,242 @@
+<style>
+    th label {
+        display: inline-block;
+        width: 60px;
+        margin-left: 10px;
+    }
+    .lineLi {
+        display: inline-block;
+        min-width: 150px;
+        font-size: 14px;
+    }
+    .page .fixed-bar .item-title h3 {
+        margin-top: 18px !important;
+        margin-bottom: 10px !important;
+        font-weight: 700 !important;
+    }
+    .tab-base li span {
+        font-size: 12px !important;
+    }
+    .layui-form-select .layui-input {
+        height: 23px;
+        padding-left: 11px;
+        padding-right: 0 !important;
+    }
+    input::placeholder {
+        color: #333;
+    }
+    .layui-form-selected dl {
+        display: flex !important;
+        flex-wrap: wrap !important;
+    }
+    .layui-form-select dl {
+        top: 29px !important;
+        left: 4px !important;
+        min-width: 802% !important;
+        max-height: 280px !important;
+        padding: 14px 0 !important;
+    }
+    .layui-form-select dl dd.layui-this {
+        display: none;
+    }
+    .layui-form-select dl dd {
+        cursor: pointer;
+        width: 130px;
+    }
+</style>
+
+<?php defined('InShopNC') or exit('Access Invalid!'); ?>
+<div class="page">
+    <div class="fixed-bar">
+        <div class="item-title">
+            <h3>信息列表</h3>
+            <ul class="tab-base">
+                <li><a href="JavaScript:void(0);" class="current"><span>信息列表</span></a></li>
+            </ul>
+        </div>
+    </div>
+    <div class="fixed-empty"></div>
+    <form method="get" action="index.php" name="formSearch" id="formSearch">
+        <input type="hidden" name="act" value="retail"/>
+        <input type="hidden" name="op" value="index"/>
+
+        <table class="tb-type1 noborder search">
+            <tr>
+                <th><label>提交状态</label></th>
+                <td>
+
+                    <select name="state" class="querySelect">
+                        <option value=""><?php echo $lang['nc_please_choose']; ?></option>
+                        <option value="<?php echo retailModel::state_init?>"
+                                <?php if ($_GET['state'] == '0'){ ?>selected<?php } ?>>未提交
+                        </option>
+                        <option value="<?php echo retailModel::state_commit?>"
+                                <?php if ($_GET['state'] == '1'){ ?>selected<?php } ?>>已提交
+                        </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>
+
+        <table class="tb-type1 noborder search">
+            <tr>
+                <td>
+                    <a href="#" class="btns"  id="dispose">
+                        <span><i class="icon-edit"></i>批量标记为已提交</span>
+                    </a>
+                </td>
+            </tr>
+        </table>
+    </form>
+    <table class="table tb-type2 nobdb">
+        <thead>
+        <tr class="thead">
+            <th class="align-center" id="selectAll">
+                <input type="checkbox" name="chbox" value="">
+            </th>
+            <th class="align-left">编号</th>
+            <th class="align-left">信息编号</th>
+            <th class="align-left">渠道code</th>
+            <th class="align-left">省市区</th>
+            <th class="align-left">详细地址</th>
+            <th class="align-left">联系人</th>
+            <th class="align-left">联系电话</th>
+            <th class="align-left">身份证号码</th>
+            <th class="align-center">收集日期</th>
+            <th class="align-center">是否提交</th>
+            <th class="align-center"><?php echo $lang['nc_handle']; ?></th>
+        </tr>
+        </thead>
+        <tbody id="tbody">
+        <?php if (count($output['list']) > 0) { ?>
+            <?php
+            foreach ($output['list'] as $key => $value) { ?>
+                <tr class="hover trFlex">
+                    <td class="align-center">
+                        <input type="checkbox" id="checkBoxList" name="checkbox" value="<?php echo $value['retail_id'];?>">
+                    </td>
+                    <td class="align-left"><?php echo $key+1;?></td>
+                    <td class="align-left"><?php echo $value['retail_sn']; ?></td>
+                    <td class="align-left"><?php echo $value['channel_code'];?></td>
+                    <td class="align-left"><?php echo "{$value['province']}-{$value['city']}-{$value['area']}"; ?></td>
+                    <td class="align-left"><?php echo $value['address']; ?></td>
+                    <td class="align-left"><?php echo $value['applicant_name']; ?></td>
+                    <td class="align-left"><?php echo $value['contact_phone']; ?></td>
+                    <td class="align-left"><?php echo $value['id_card']; ?></td>
+                    <td class="align-center"><?php echo date('Y-m-d H:i:s', $value['create_time']) ?? '/'; ?></td>
+                    <td class="align-center">
+                        <?php if ($value['state'] == '1') { ?>
+                            <span style="color: #0bb20c">
+                        <?php } ?>
+                        <?php if ($value['state'] == '0') { ?>
+                            <span style="color: #f30707">
+                        <?php } ?>
+                            <?php echo $output['state_text'][$value['state']]; ?>
+                        </span>
+                    </td>
+                    <td class="align-center">
+                        <a href="index.php?act=retail&op=retail_dispose&id=<?php echo $value['retail_id']; ?>">
+                            标记为已提交</a>
+                    </td>
+                </tr>
+            <?php } ?>
+        <?php } else { ?>
+            <tr class="no_data">
+                <td colspan="11"><?php echo $lang['nc_no_record']; ?></td>
+            </tr>
+        <?php } ?>
+        </tbody>
+        <tfoot>
+        <tr class="tfoot">
+            <td colspan="11" id="dataFuncs">
+                <div class="pagination"> <?php echo $output['show_page']; ?> </div>
+            </td>
+        </tr>
+        </tfoot>
+    </table>
+    <!-- 预警提示 -->
+    <audio id="auto" src="<?php echo RESOURCE_SITE_URL; ?>/warning.mp3"></audio>
+</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 ADMIN_TEMPLATES_URL;?>/layui/layui.js"></script>
+<link rel="stylesheet" type="text/css" href="<?php echo ADMIN_TEMPLATES_URL; ?>/layui/css/layui.css"/>
+<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 () {
+        $('#ncsubmit').click(function () {
+            $('#formSearch').submit();
+        });
+
+        $('#query_start_time').datepicker({dateFormat: 'yy-mm-dd'});
+        $('#query_end_time').datepicker({dateFormat: 'yy-mm-dd'});
+        // 日期选择器
+        laydate.render({
+            elem: '#startTime',
+            type: 'datetime'
+        });
+        laydate.render({
+            elem: '#endTime',
+            type: 'datetime'
+        });
+
+        //全选
+        $('#selectAll' ).click ( function () {
+            if ($("input[name='chbox']").is(':checked')) {
+                $("input[name='checkbox']").each(function() {
+                    this.checked = true;
+                })
+            } else {
+                $("input[name='checkbox']").each(function() {
+                    this.checked = false;
+                })
+            }
+        })
+
+        let get_sel_id = function (){
+            let arr = [];
+            $("input:checkbox:checked").each(function () {
+                let sel_id = $(this).val();
+                if(sel_id !== '') {
+                    arr.push(sel_id);
+                }
+            })
+            if (arr.length <= 0) { return}
+            return arr.join(",")
+        }
+
+        //批量失败
+        $('#dispose').click(function () {
+            layer.confirm('您确定要批量处理为已提交吗', {
+                btn: ['确定', '取消'],
+                title: '批量处理'
+            }, function () {
+                const batch = get_sel_id();
+                window.location.href = `index.php?act=retail&op=retail_dispose&id= ${batch ? batch : ''}`
+            }, function () {
+                layer.msg('取消成功')
+            });
+        })
+
+        // 表格hover时背景
+        $('.trFlex').each(function () {
+            let data_color = $(this).attr('data-timeout_State');
+            $(this).css('background', '#fff')
+            $(this).hover(function () {
+                $(this)[0].style.backgroundColor = '#cbe9f3'
+            }, function () {
+                $(this).css('background', '#fff')
+            })
+        })
+    })
+
+</script>

+ 162 - 24
data/config/xyz/refill.ini.php

@@ -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'];
 
@@ -6215,34 +6215,34 @@ $xinruiheng_phone = ['name' => 'xinruiheng', 'store_id' => 235, 'qualitys' => '1
 //        ],
         30 => [
             ['goods_id' => 7945, 'price' => 28.98, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7945, 'price' => 28.35, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7945, 'price' => 28.26, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7945, 'price' => 28.41, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         50 => [
             ['goods_id' => 7946, 'price' => 48.3, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7946, 'price' => 47.25, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7946, 'price' => 47.1, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7946, 'price' => 47.35, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         100 => [
             ['goods_id' => 7947, 'price' => 96.6, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7947, 'price' => 94.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7947, 'price' => 94.2, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7947, 'price' => 94.7, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         200 => [
             ['goods_id' => 7948, 'price' => 193.2, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7948, 'price' => 189, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7948, 'price' => 188.4, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7948, 'price' => 189.4, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
-//        300 => [
+        300 => [
 //            ['goods_id' => 7949, 'price' => 289.8, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7949, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7949, 'price' => 282.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7949, 'price' => 284.1, 'quality' => 1, 'card_type' => 'chinatelecom']
-//        ],
-//        500 => [
+        ],
+        500 => [
 //            ['goods_id' => 7950, 'price' => 483, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7950, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7950, 'price' => 471, 'quality' => 1, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7950, 'price' => 473.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-//        ]
+        ]
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -6571,17 +6571,152 @@ $weixue_phone = ['name' => 'weixue', 'store_id' => 243, 'qualitys' => '1',
             ['goods_id' => 8012, 'price' => 193.4, 'quality' => 1, 'card_type' => 'chinamobile'],
             ['goods_id' => 8012, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom']
         ],
-//        300 => [
+        300 => [
 //            ['goods_id' => 8013, 'price' => 290.1, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 8013, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom']
+            ['goods_id' => 8013, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ],
+        500 => [
+//            ['goods_id' => 8014, 'price' => 483.5, 'quality' => 1, 'card_type' => 'chinamobile'],
+            ['goods_id' => 8014, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom']
+        ]
+    ],
+    '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' => 8014, 'price' => 483.5, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 8014, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom']
+//            ['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'];
+
+$yingdian_hf_phone = ['name' => 'yingdian_hf', 'store_id' => 246, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 8031, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8031, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8031, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 8032, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8032, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8032, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        30 => [
+//            ['goods_id' => 8033, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8033, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8033, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        50 => [
+            ['goods_id' => 8034, 'price' => 49, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8034, 'price' => 49, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8034, 'price' => 49, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 8035, 'price' => 98, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8035, 'price' => 98, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8035, 'price' => 98, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 8036, 'price' => 196, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8036, 'price' => 196, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8036, 'price' => 196, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        300 => [
+            ['goods_id' => 8037, 'price' => 294, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8037, 'price' => 294, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8037, 'price' => 294, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        500 => [
+            ['goods_id' => 8038, 'price' => 490, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 8038, 'price' => 490, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 8038, 'price' => 490, '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 +6917,9 @@ $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],
+    ['name' => 'yingdian_hf', 'cfg' => $yingdian_hf_phone],
 
 ];
 $config['phone_providers'] = $phone_providers;

+ 117 - 24
data/config/yl/refill.ini.php

@@ -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'];
 
@@ -6046,34 +6046,34 @@ $xinruiheng_phone = ['name' => 'xinruiheng', 'store_id' => 226, 'qualitys' => '1
 //        ],
         30 => [
             ['goods_id' => 7900, 'price' => 28.98, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7900, 'price' => 28.35, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7900, 'price' => 28.26, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7900, 'price' => 28.41, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         50 => [
             ['goods_id' => 7901, 'price' => 48.3, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7901, 'price' => 47.25, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7901, 'price' => 47.1, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7901, 'price' => 47.35, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         100 => [
             ['goods_id' => 7902, 'price' => 96.6, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7902, 'price' => 94.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7902, 'price' => 94.2, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7902, 'price' => 94.7, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
         200 => [
             ['goods_id' => 7903, 'price' => 193.2, 'quality' => 1, 'card_type' => 'chinamobile'],
-            ['goods_id' => 7903, 'price' => 189, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7903, 'price' => 188.4, 'quality' => 1, 'card_type' => 'chinaunicom'],
             ['goods_id' => 7903, 'price' => 189.4, 'quality' => 1, 'card_type' => 'chinatelecom']
         ],
-//        300 => [
+        300 => [
 //            ['goods_id' => 7904, 'price' => 289.8, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7904, 'price' => 283.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7904, 'price' => 282.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7904, 'price' => 284.1, 'quality' => 1, 'card_type' => 'chinatelecom']
-//        ],
-//        500 => [
+        ],
+        500 => [
 //            ['goods_id' => 7905, 'price' => 483, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7905, 'price' => 472.5, 'quality' => 1, 'card_type' => 'chinaunicom'],
+            ['goods_id' => 7905, 'price' => 471, 'quality' => 1, 'card_type' => 'chinaunicom'],
 //            ['goods_id' => 7905, 'price' => 473.5, 'quality' => 1, 'card_type' => 'chinatelecom']
-//        ]
+        ]
     ],
     'official_sn' => true, 'refill_type' => 'api'];
 
@@ -6403,17 +6403,107 @@ $weixue_phone = ['name' => 'weixue', 'store_id' => 235, 'qualitys' => '1',
             ['goods_id' => 7968, 'price' => 193.4, 'quality' => 1, 'card_type' => 'chinamobile'],
             ['goods_id' => 7968, 'price' => 190, 'quality' => 1, 'card_type' => 'chinaunicom']
         ],
-//        300 => [
+        300 => [
 //            ['goods_id' => 7969, 'price' => 290.1, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7969, 'price' => 285, 'quality' => 1, 'card_type' => 'chinaunicom']
+            ['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' => 7970, 'price' => 483.5, 'quality' => 1, 'card_type' => 'chinamobile'],
-//            ['goods_id' => 7970, 'price' => 475, 'quality' => 1, 'card_type' => 'chinaunicom']
+//            ['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'];
 
+$yingdian_hf_phone = ['name' => 'yingdian_hf', 'store_id' => 237, 'qualitys' => '1',
+    'amount' => [
+//        10 => [
+//            ['goods_id' => 7979, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7979, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7979, 'price' => 9.8, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        20 => [
+//            ['goods_id' => 7980, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7980, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7980, 'price' => 19.6, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+//        30 => [
+//            ['goods_id' => 7981, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7981, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7981, 'price' => 29.4, 'quality' => 1, 'card_type' => 'chinatelecom']
+//        ],
+        50 => [
+            ['goods_id' => 7982, 'price' => 49, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7982, 'price' => 49, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7982, 'price' => 49, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        100 => [
+            ['goods_id' => 7983, 'price' => 98, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7983, 'price' => 98, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7983, 'price' => 98, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        200 => [
+            ['goods_id' => 7984, 'price' => 196, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7984, 'price' => 196, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7984, 'price' => 196, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        300 => [
+            ['goods_id' => 7985, 'price' => 294, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7985, 'price' => 294, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7985, 'price' => 294, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ],
+        500 => [
+            ['goods_id' => 7986, 'price' => 490, 'quality' => 1, 'card_type' => 'chinamobile'],
+//            ['goods_id' => 7986, 'price' => 490, 'quality' => 1, 'card_type' => 'chinaunicom'],
+//            ['goods_id' => 7986, 'price' => 490, 'quality' => 1, 'card_type' => 'chinatelecom']
+        ]
+    ],
+    'official_sn' => true, 'refill_type' => 'api'];
+
 $phone_providers = [
 //    ['name' => 'beixt', 'cfg' => $beixt_phone],
 //    ['name' => 'bxtwt', 'cfg' => $bxtwt_phone],
@@ -6610,6 +6700,9 @@ $phone_providers = [
     ['name' => 'dazhanggui', 'cfg' => $dazhanggui_phone],
     ['name' => 'yezi_hf', 'cfg' => $yezi_hf_phone],
     ['name' => 'weixue', 'cfg' => $weixue_phone],
+    ['name' => 'dazhanggui_high', 'cfg' => $dazhanggui_high_phone],
+    ['name' => 'yingdian_hf', 'cfg' => $yingdian_hf_phone],
+
 ];
 $config['phone_providers'] = $phone_providers;
 

+ 27 - 0
data/model/retail.model.php

@@ -0,0 +1,27 @@
+<?php
+
+defined('InShopNC') or exit('Access Invalid!');
+
+class retailModel extends Model
+{
+    const state_init = 0;
+    const state_commit = 1;
+
+    public function __construct()
+    {
+        parent::__construct('retail');
+    }
+
+    public function getList($condition, $pagesize = '',$total = 0, $field = '*', $order = 'create_time asc', $limit = '', $master = false)
+    {
+        $list = $this->field($field)->where($condition)->page($pagesize,$total)->order($order)->limit($limit)->master($master)->select();
+        if (empty($list)) return [];
+        return $list;
+    }
+
+    public function dispose_commit($cond)
+    {
+        $cond['state'] = self::state_init;
+        return $this->where($cond)->update(['state' => self::state_commit]);
+    }
+}

+ 1 - 0
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;']
 

+ 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/20220916辽宁青海移动调价函.jpg


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

@@ -64,10 +64,10 @@ class config
     const Price = [
         //移动
         "4-10-2" => 10.15, "4-20-2" => 19.92, "4-30-2" => 29.94, "4-50-2" => 49.9, "4-100-2" => 99.8, "4-200-2" => 199.6, "4-300-2" => 299.4, "4-500-2" => 499,//天津 2
-        "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-6" => 9.81, "4-20-6" => 19.62, "4-30-6" => 29.43, "4-50-6" => 49.05, "4-100-6" => 98.1, "4-200-6" => 196.2, "4-300-6" => 294.3, "4-500-6" => 490.5,//辽宁 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.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-29" => 9.835, "4-20-29" => 19.67, "4-30-29" => 29.505, "4-50-29" => 49.175, "4-100-29" => 98.35, "4-200-29" => 196.7, "4-300-29" => 295.05, "4-500-29" => 491.75,//青海 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

BIN
helper/refill/api/xyz/tianyi/800系统接口文档/【1.优先详看】天翼流量800新接口协议(2021.11).pdf


+ 187 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/C#加密模版.txt

@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+
+public partial class dx : System.Web.UI.Page
+{
+    protected void Page_Load(object sender, EventArgs e)
+    {
+        string url = "http://118.123.170.72:8888/fps/flowService.do";
+ 
+     string codes="{\"request_no\":\"123\",\"service_code\":\"FS0001\",\"contract_id\":\"AccessPartner2014\",\"order_id\":\"0\",\"plat_offer_id\":\"100091\",\"phone_id\":\"18017017801\",\"activity_id\":\"100085\",\"order_type\":\"1\",\"channel_id\":\"1\"}";
+ 
+        byte[] encryptData = Encrypts(codes, "H5gOs1ZshKZ6WikN", "8888159601152533");
+        string content = Str2Hex(encryptData).ToLower();
+     
+        string p = "{\"partner_no\":\"100054374\",\"code\":\"" + content + "\"}";
+  
+ 
+      string ok = Common.Fun.MyPost(url, p);
+     Response.Write(ok);
+
+    }
+
+    /// <summary>
+    /// 字节转16进制
+    /// </summary>
+    /// <param name="s"></param>
+    /// <returns></returns>
+    public static string Str2Hex(byte[] s)
+    {
+        System.Text.StringBuilder strBuf = new System.Text.StringBuilder();
+     
+        
+        //byte[] arrByte = System.Text.Encoding.GetEncoding("GB2312").GetBytes(s);
+
+
+        for (int i = 0; i < s.Length; i++)
+          {
+              strBuf.Append((char)(((s[i] >> 4) & 0xF) + ((int)'a')));
+              strBuf.Append((char)(((s[i]) & 0xF) + ((int)'a')));
+          }
+          return strBuf.ToString();
+    } 

+ 
+ 
+    /// <summary>
+    /// AES-128-CBC
+    /// </summary>
+    /// <param name="toEncrypt"></param>
+    /// <param name="key"></param>
+    /// <param name="iv"></param>
+    /// <returns></returns>
+
+    public static byte[] Encrypts(string toEncrypt, string key, string iv)
+    {
+
+
+        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
+        byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
+
+
+        byte[] resultArray = EncryptStringToBytes_Aes(toEncrypt, keyArray, ivArray);
+        return resultArray;
+
+    }
+
+
+    /// <summary>
+    /// AES-128-CBC  加密处理
+    /// </summary>
+    /// <param name="plainText"></param>
+    /// <param name="Key"></param>
+    /// <param name="IV"></param>
+    /// <returns></returns>
+   public  static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
+    {
+        // Check arguments.
+        if (plainText == null || plainText.Length <= 0)
+            throw new ArgumentNullException("plainText");
+        if (Key == null || Key.Length <= 0)
+            throw new ArgumentNullException("Key");
+        if (IV == null || IV.Length <= 0)
+            throw new ArgumentNullException("Key");
+        byte[] encrypted;
+        // Create an AesCryptoServiceProvider object
+        // with the specified key and IV.
+        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
+        {
+            aesAlg.Key = Key;
+            aesAlg.IV = IV;
+
+            // Create a decrytor to perform the stream transform.
+            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+
+            // Create the streams used for encryption.
+            using (MemoryStream msEncrypt = new MemoryStream())
+            {
+                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+                {
+                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
+                    {
+
+                        //Write all data to the stream.
+                        swEncrypt.Write(plainText);
+                    }
+                    encrypted = msEncrypt.ToArray();
+                }
+            }
+        }
+
+
+        // Return the encrypted bytes from the memory stream.
+        return encrypted;
+
+    }
+
+
+    public static DataTable JsonToDataTable(string strJson)
+    {
+        //取出表名   
+        var rg = new Regex(@"(?<={)[^:]+(?=:\[)", RegexOptions.IgnoreCase);
+        string strName = rg.Match(strJson).Value;
+        DataTable tb = null;
+        //去除表名   
+        // strJson = strJson.Substring(strJson.IndexOf("[") + 1);
+        //strJson = strJson.Substring(0, strJson.IndexOf("]"));
+
+        //获取数据   
+        rg = new Regex(@"(?<={)[^}]+(?=})");
+        MatchCollection mc = rg.Matches(strJson);
+        for (int i = 0; i < mc.Count; i++)
+        {
+            string strRow = mc[i].Value;
+            string[] strRows = strRow.Split(',');
+
+            //创建表   
+            if (tb == null)
+            {
+                tb = new DataTable();
+                tb.TableName = strName;
+                foreach (string str in strRows)
+                {
+                    var dc = new DataColumn();
+                    string[] strCell = str.Split(':');
+                    dc.ColumnName = strCell[0];
+                    dc.ColumnName = dc.ColumnName.Replace("\"", "");
+                    tb.Columns.Add(dc);
+                }
+                tb.AcceptChanges();
+            }
+
+            //增加内容   
+            DataRow dr = tb.NewRow();
+            for (int r = 0; r < strRows.Length; r++)
+            {
+                string str = "";
+                if (strRows[r].Split(':')[1].Trim().IndexOf("http") > -1)
+                {
+                    dr[r] = strRows[r].Split(':')[1].Trim().Replace(",", ",").Replace(":", ":").Replace("\"", "") + ":" + strRows[r].Split(':')[2].Trim().Replace(",", ",").Replace(":", ":").Replace("\"", "").Replace("\\", "");
+                }
+                else
+                {
+                    dr[r] = strRows[r].Split(':')[1].Trim().Replace(",", ",").Replace(":", ":").Replace("\"", "");
+                }
+
+
+            }
+            tb.Rows.Add(dr);
+            tb.AcceptChanges();
+        }
+
+        return tb;
+    }
+}
+
+
+ 
+ 
+ 

+ 424 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/C++ AES加密模板.txt

@@ -0,0 +1,424 @@
+/*AES接口*/
+
+#ifndef SRC_UTILS_AES_H
+#define SRC_UTILS_AES_H
+
+class AES  
+{
+public:
+    AES(unsigned char* key);
+    virtual ~AES();
+    unsigned char* Cipher(unsigned char* input);    // 加密,传入的数组大小必须是16字节
+    unsigned char* InvCipher(unsigned char* input);  // 解密,传入的数组也必须是16字节
+    void* Cipher(void* input, int length=0);      // 可以传入数组,大小必须是16的整数倍,如果不是将会越界操作;如果不传length而默认为0,那么将按照字符串处理,遇'\0'结束
+    void* InvCipher(void* input, int length);      // 必须传入数组和大小,必须是16的整数倍
+
+private:
+    unsigned char Sbox[256];
+    unsigned char InvSbox[256];
+    unsigned char w[11][4][4];
+
+    void KeyExpansion(unsigned char* key, unsigned char w[][4][4]);
+    unsigned char FFmul(unsigned char a, unsigned char b);
+
+    void SubBytes(unsigned char state[][4]);
+    void ShiftRows(unsigned char state[][4]);
+    void MixColumns(unsigned char state[][4]);
+    void AddRoundKey(unsigned char state[][4], unsigned char k[][4]);
+
+    void InvSubBytes(unsigned char state[][4]);
+    void InvShiftRows(unsigned char state[][4]);
+    void InvMixColumns(unsigned char state[][4]);
+};
+
+#endif    // SRC_UTILS_AES_H
+
+
+/*AES实现*/
+
+#include "aes.h"
+#include "string.h"
+
+AES::AES(unsigned char* key)
+{
+    unsigned char sBox[] =
+    { /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f */ 
+        0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, /*0*/  
+        0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, /*1*/
+        0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, /*2*/ 
+        0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, /*3*/ 
+        0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, /*4*/ 
+        0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, /*5*/
+        0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, /*6*/  
+        0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, /*7*/ 
+        0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, /*8*/ 
+        0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, /*9*/ 
+        0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, /*a*/
+        0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, /*b*/
+        0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, /*c*/ 
+        0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, /*d*/
+        0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, /*e*/ 
+        0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16  /*f*/
+    };
+    unsigned char invsBox[256] = 
+    { /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f  */  
+        0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, /*0*/ 
+        0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, /*1*/
+        0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, /*2*/ 
+        0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, /*3*/ 
+        0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, /*4*/ 
+        0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, /*5*/ 
+        0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, /*6*/ 
+        0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, /*7*/
+        0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, /*8*/ 
+        0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, /*9*/
+        0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, /*a*/
+        0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, /*b*/ 
+        0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, /*c*/ 
+        0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, /*d*/ 
+        0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, /*e*/ 
+        0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d  /*f*/
+    }; 
+    memcpy(Sbox, sBox, 256);
+    memcpy(InvSbox, invsBox, 256);
+    KeyExpansion(key, w);
+}
+
+AES::~AES()
+{
+
+}
+
+unsigned char* AES::Cipher(unsigned char* input)
+{
+    unsigned char state[4][4];
+    int i,r,c;
+
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4 ;c++)
+        {
+            state[r][c] = input[c*4+r];
+        }
+    }
+
+    AddRoundKey(state,w[0]);
+
+    for(i=1; i<=10; i++)
+    {
+        SubBytes(state);
+        ShiftRows(state);
+        if(i!=10)MixColumns(state);
+        AddRoundKey(state,w[i]);
+    }
+
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4 ;c++)
+        {
+            input[c*4+r] = state[r][c];
+        }
+    }
+
+    return input;
+}
+
+unsigned char* AES::InvCipher(unsigned char* input)
+{
+    unsigned char state[4][4];
+    int i,r,c;
+
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4 ;c++)
+        {
+            state[r][c] = input[c*4+r];
+        }
+    }
+
+    AddRoundKey(state, w[10]);
+    for(i=9; i>=0; i--)
+    {
+        InvShiftRows(state);
+        InvSubBytes(state);
+        AddRoundKey(state, w[i]);
+        if(i)
+        {
+            InvMixColumns(state);
+        }
+    }
+    
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4 ;c++)
+        {
+            input[c*4+r] = state[r][c];
+        }
+    }
+
+    return input;
+}
+
+void* AES::Cipher(void* input, int length)
+{
+    unsigned char* in = (unsigned char*) input;
+    int i;
+    if(!length)        // 如果是0则当做字符串处理
+    {
+        while(*(in+length++));
+        in = (unsigned char*) input;
+    }
+    for(i=0; i<length; i+=16)
+    {
+        Cipher(in+i);
+    }
+    return input;
+}
+
+void* AES::InvCipher(void* input, int length)
+{
+    unsigned char* in = (unsigned char*) input;
+    int i;
+    for(i=0; i<length; i+=16)
+    {
+        InvCipher(in+i);
+    }
+    return input;
+}
+
+void AES::KeyExpansion(unsigned char* key, unsigned char w[][4][4])
+{
+    int i,j,r,c;
+    unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4; c++)
+        {
+            w[0][r][c] = key[r+c*4];
+        }
+    }
+    for(i=1; i<=10; i++)
+    {
+        for(j=0; j<4; j++)
+        {
+            unsigned char t[4];
+            for(r=0; r<4; r++)
+            {
+                t[r] = j ? w[i][r][j-1] : w[i-1][r][3];
+            }
+            if(j == 0)
+            {
+                unsigned char temp = t[0];
+                for(r=0; r<3; r++)
+                {
+                    t[r] = Sbox[t[(r+1)%4]];
+                }
+                t[3] = Sbox[temp];
+                t[0] ^= rc[i-1];
+            }
+            for(r=0; r<4; r++)
+            {
+                w[i][r][j] = w[i-1][r][j] ^ t[r];
+            }
+        }
+    }
+}
+
+unsigned char AES::FFmul(unsigned char a, unsigned char b)
+{
+    unsigned char bw[4];
+    unsigned char res=0;
+    int i;
+    bw[0] = b;
+    for(i=1; i<4; i++)
+    {
+        bw[i] = bw[i-1]<<1;
+        if(bw[i-1]&0x80)
+        {
+            bw[i]^=0x1b;
+        }
+    }
+    for(i=0; i<4; i++)
+    {
+        if((a>>i)&0x01)
+        {
+            res ^= bw[i];
+        }
+    }
+    return res;
+}
+
+void AES::SubBytes(unsigned char state[][4])
+{
+    int r,c;
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4; c++)
+        {
+            state[r][c] = Sbox[state[r][c]];
+        }
+    }
+}
+
+void AES::ShiftRows(unsigned char state[][4])
+{
+    unsigned char t[4];
+    int r,c;
+    for(r=1; r<4; r++)
+    {
+        for(c=0; c<4; c++)
+        {
+            t[c] = state[r][(c+r)%4];
+        }
+        for(c=0; c<4; c++)
+        {
+            state[r][c] = t[c];
+        }
+    }
+}
+
+void AES::MixColumns(unsigned char state[][4])
+{
+    unsigned char t[4];
+    int r,c;
+    for(c=0; c< 4; c++)
+    {
+        for(r=0; r<4; r++)
+        {
+            t[r] = state[r][c];
+        }
+        for(r=0; r<4; r++)
+        {
+            state[r][c] = FFmul(0x02, t[r])
+                        ^ FFmul(0x03, t[(r+1)%4])
+                        ^ FFmul(0x01, t[(r+2)%4])
+                        ^ FFmul(0x01, t[(r+3)%4]);
+        }
+    }
+}
+
+void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4])
+{
+    int r,c;
+    for(c=0; c<4; c++)
+    {
+        for(r=0; r<4; r++)
+        {
+            state[r][c] ^= k[r][c];
+        }
+    }
+}
+
+void AES::InvSubBytes(unsigned char state[][4])
+{
+    int r,c;
+    for(r=0; r<4; r++)
+    {
+        for(c=0; c<4; c++)
+        {
+            state[r][c] = InvSbox[state[r][c]];
+        }
+    }
+}
+
+void AES::InvShiftRows(unsigned char state[][4])
+{
+    unsigned char t[4];
+    int r,c;
+    for(r=1; r<4; r++)
+    {
+        for(c=0; c<4; c++)
+        {
+            t[c] = state[r][(c-r+4)%4];
+        }
+        for(c=0; c<4; c++)
+        {
+            state[r][c] = t[c];
+        }
+    }
+}
+
+void AES::InvMixColumns(unsigned char state[][4])
+{
+    unsigned char t[4];
+    int r,c;
+    for(c=0; c< 4; c++)
+    {
+        for(r=0; r<4; r++)
+        {
+            t[r] = state[r][c];
+        }
+        for(r=0; r<4; r++)
+        {
+            state[r][c] = FFmul(0x0e, t[r])
+                        ^ FFmul(0x0b, t[(r+1)%4])
+                        ^ FFmul(0x0d, t[(r+2)%4])
+                        ^ FFmul(0x09, t[(r+3)%4]);
+        }
+    }
+}
+
+
+/*加解密类*/
+
+#include "aes.h"
+#include "aes_encryptor.h"
+#include "log.h"
+
+#include <fstream>
+using namespace std;
+
+AesEncryptor::AesEncryptor(unsigned char* key)
+{
+    m_pEncryptor = new AES(key);
+}
+
+
+AesEncryptor::~AesEncryptor(void)
+{
+    delete m_pEncryptor;
+}
+
+void AesEncryptor::Byte2Hex(const unsigned char* src, int len, char* dest) {
+    for (int i=0; i<len; ++i) {
+        sprintf_s(dest + i * 2, 3, "%02X", src[i]);    
+    }
+}
+
+void AesEncryptor::Hex2Byte(const char* src, int len, unsigned char* dest) {
+    int length = len / 2;
+    for (int i=0; i<length; ++i) {
+        dest[i] = Char2Int(src[i * 2]) * 16 + Char2Int(src[i * 2 + 1]);
+    }
+}
+
+string AesEncryptor::EncryptString(string strInfor) {
+    int nLength = strInfor.length();
+    int spaceLength = 16 - (nLength % 16);
+    unsigned char* pBuffer = new unsigned char[nLength + spaceLength];
+    memset(pBuffer, '\0', nLength + spaceLength);
+    memcpy_s(pBuffer, nLength + spaceLength, strInfor.c_str(), nLength);
+    m_pEncryptor->Cipher(pBuffer, nLength + spaceLength);
+    
+    // 这里需要把得到的字符数组转换成十六进制字符串 
+    char* pOut = new char[2 * (nLength + spaceLength)];
+    memset(pOut, '\0', 2 * (nLength + spaceLength));
+    Byte2Hex(pBuffer, nLength + spaceLength, pOut);
+
+    string retValue(pOut);
+    delete[] pBuffer;
+    delete[] pOut;
+    return retValue;
+}
+
+string AesEncryptor::DecryptString(string strMessage) {
+    int nLength = strMessage.length() / 2;
+    unsigned char* pBuffer = new unsigned char[nLength];
+    memset(pBuffer, '\0', nLength);
+    Hex2Byte(strMessage.c_str(), strMessage.length(), pBuffer);
+
+    m_pEncryptor->InvCipher(pBuffer, nLength);
+    string retValue((char*)pBuffer);
+    delete[] pBuffer;
+    return retValue;
+}

+ 115 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/Java AES加密模板.java

@@ -0,0 +1,115 @@
+package com._21cn;
+
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * AES-128-CBC加解密模式
+ * @author libai
+ */
+public class AES {
+	
+	/**
+	 * 加密方法(此方法已经包含了将加密生成二进制加密串转为纯字母型的十六进制串的操作)
+	 * @param encData 要加密的数据
+	 * @param secretKey 密钥 ,16位的数字和字母
+	 * @param vector 初始化向量,16位的数字和字母
+	 * @return
+	 * @throws NoSuchPaddingException 
+	 * @throws NoSuchAlgorithmException 
+	 * @throws InvalidAlgorithmParameterException 
+	 * @throws InvalidKeyException 
+	 * @throws BadPaddingException 
+	 * @throws IllegalBlockSizeException 
+	 * @throws Exception
+	 */
+	public static String Encrypt(String encData ,String secretKey,String vector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException  {
+		
+		if(secretKey == null) {
+			return null;
+		}
+		if(secretKey.length() != 16) {
+			return null;
+		}
+		byte[] raw = secretKey.getBytes();
+		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
+		IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
+		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
+		byte[] encrypted = cipher.doFinal(encData.getBytes());
+		return encodeBytes( encrypted );	//将加密生成二进制加密串转为纯字母型的十六进制串后返回
+	}
+
+	/**
+	 * 解密方法(此方法已经包含了将纯字母型的十六进制串转为二进制加密串的操作)
+	 * @param decData
+	 * @param secretKey 密钥 ,16位的数字和字母
+	 * @param vector 初始化向量,16位的数字和字母
+	 * @return
+	 * @throws UnsupportedEncodingException 
+	 * @throws NoSuchPaddingException 
+	 * @throws NoSuchAlgorithmException 
+	 * @throws InvalidAlgorithmParameterException 
+	 * @throws InvalidKeyException 
+	 * @throws BadPaddingException 
+	 * @throws IllegalBlockSizeException 
+	 * @throws Exception
+	 */
+	public static String Decrypt(String decData ,String secretKey,String vector) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
+		
+		if(secretKey == null) {
+			return null;
+		}
+		if(secretKey.length() != 16) {
+			return null;
+		}
+		byte[] raw = secretKey.getBytes("ASCII");
+		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+		IvParameterSpec iv = new IvParameterSpec(vector.getBytes());
+		cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+		byte[] encrypted1 = decodeBytes(decData);	//解密前先将纯字母型的十六进制串转为二进制加密串
+		byte[] original = cipher.doFinal(encrypted1);
+		String originalString = new String(original);
+		return originalString;
+	}
+
+	/**
+	 * 转16进制
+	 * @param bytes
+	 * @return
+	 */
+	public static String encodeBytes(byte[] bytes) {
+		StringBuffer strBuf = new StringBuffer();
+		for (int i = 0; i < bytes.length; i++) {
+			strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
+			strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
+		}
+		return strBuf.toString();
+	}
+
+	/**
+	 * 转字节数组
+	 * @param str
+	 * @return
+	 */
+	public static byte[] decodeBytes(String str) {
+		byte[] bytes = new byte[str.length() / 2];
+		for (int i = 0; i < str.length(); i += 2) {
+			char c = str.charAt(i);
+			bytes[i / 2] = (byte) ((c - 'a') << 4);
+			c = str.charAt(i + 1);
+			bytes[i / 2] += (c - 'a');
+		}
+		return bytes;
+	}		
+}

+ 54 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/php AES加密模板.php

@@ -0,0 +1,54 @@
+<?php
+
+class AES{
+
+    private static function decodeBytes($hex)
+    {   
+        $str = ''; 
+        for($i=0;$i<strlen($hex);$i+=2){     	
+        	$tmpValue = (((ord($hex[$i]) - ord('a')) & 0xf ) <<4) + ((ord($hex[$i+1])- ord('a')) & 0xf);  
+        	$str .= chr($tmpValue); 
+        }
+        return  $str;
+    }
+    
+    private static function encodeBytes($string)
+    { 
+        $str = ''; 
+        for($i=0;$i<strlen($string);$i++)
+        {
+            $tmpValue = ord($string[$i]); 
+            $ch = ($tmpValue >> 4 & 0xf) + ord('a'); 
+            $str .= chr($ch); 
+            $ch = ($tmpValue & 0xf) + ord('a'); 
+            $str .= chr($ch); 
+        }
+        return $str;
+    }
+    /**
+     * 解密数据
+     * @param String $encryptedText 待解密密文 
+     * @param String $secretKey 密钥
+     * @param String $iv 向量密钥
+     * @return String
+     */
+	public static function encrypt($encryptedText, $secretKey, $iv) {
+		
+        $ciphertext = openssl_encrypt($encryptedText, "AES-128-CBC", $secretKey, OPENSSL_RAW_DATA, $iv);
+        return self::encodeBytes($ciphertext);
+	}
+	/**
+     * 加密数据
+     * @param String $encryptedText 待加密数据
+     * @param String $secretKey 密钥
+     * @param String $iv 向量密钥
+     * @return String
+     */
+	public static function decrypt($encryptedText, $secretKey, $iv) {
+		$encryptedText = self::decodeBytes($encryptedText);
+        $plaintext = openssl_decrypt($encryptedText, "AES-128-CBC", $secretKey, OPENSSL_RAW_DATA, $iv);
+		return $plaintext;
+	}
+	
+}
+?>

+ 70 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【1】请求加密Demo/python AES加密模板.py

@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*- 
+#@author: rui.xu
+#这里使用pycrypto‎库
+#按照方法:easy_install pycrypto‎
+ 
+from Crypto.Cipher import AES
+from binascii import b2a_hex, a2b_hex
+ 
+class prpcrypt():
+    def __init__(self,key):
+        self.key = key
+        self.mode = AES.MODE_CBC
+     
+    #加密函数,如果text不足16位就用空格补足为16位,
+    #如果大于16当时不是16的倍数,那就补足为16的倍数。
+    def encrypt(self,text):
+        cryptor = AES.new(self.key,self.mode,b'0000000000000000')
+        #这里密钥key 长度必须为16(AES-128),
+        #24(AES-192),或者32 (AES-256)Bytes 长度
+        #目前AES-128 足够目前使用
+		#b'0000000000000000'为16位二进制向量
+        length = 16
+        count = len(text)
+        if count < length:
+            add = (length-count)
+            #\0 backspace
+            text = text + ('\0' * add)
+        elif count > length:
+            add = (length-(count % length))
+            text = text + ('\0' * add)
+        self.ciphertext = cryptor.encrypt(text)
+        #因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
+        #所以这里统一把加密后的字符串转化为16进制字符串
+        return encodeBytes(self.ciphertext)
+     
+    #解密后,去掉补足的空格用strip() 去掉
+    def decrypt(self,text):
+        cryptor = AES.new(self.key,self.mode,b'0000000000000000')
+		#这里密钥key 长度必须为16(AES-128),
		#b'0000000000000000'为16位二进制向量
+		
+        plain_text  = cryptor.decrypt(a2b_hex(text))
+        return plain_text.rstrip('\0')
+	
+	def encodeBytes(hexlist):
+    """
+    2进制转16进制字符串
+    :param bytelist:
+    :return:
+    """
+    in_list = []
+    for h in hexlist:
+        h = int(str(int(h.upper(), 16)))
+        if h > 128:
+            h = ~h ^ 255
+        in_list.append(int(h))
+
+    ret = []
+    for byte in in_list:
+        ret.append(chr(((byte >> 4) & 0xF) + 97))
+        ret.append(chr((byte & 0xF) + 97))
+    return ''.join(ret)
+ 
+if __name__ == '__main__':
+    pc = prpcrypt('keyskeyskeyskeys') #初始化密钥
+    import sys
+    e = pc.encrypt(sys.argv[1]) #加密
+    d = pc.decrypt(e) #解密
+    print "加密:",e
+    print "解密:",d

+ 54 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/c#回调解密.txt

@@ -0,0 +1,54 @@
+public static byte[] decodeBytes(String str)
+        {
+            byte[] bytes = new byte[str.Length / 2];
+            for (int i = 0; i < str.Length; i += 2)
+            {
+                char c = Convert.ToChar(str.Substring(i,1));
+                bytes[i / 2] = (byte)((c - 'a') << 4);
+                c = Convert.ToChar(str.Substring(i + 1,1));
+                bytes[i / 2] += Convert.ToByte(c - 'a');
+            }
+            return bytes;
+        }
+/// <summary>  
+        /// AES解密
+        /// </summary>  
+        /// <param name="Data">被加密的明文</param>  
+        /// <param name="Key">密钥</param>  
+        /// <param name="Vector">向量</param>  
+        /// <returns>明文</returns>  
+        public static string AES_Decrypt(String Data, String Key, String Vector)
+        {
+            Byte[] encryptedByte = decodeBytes(Data);
+            
+            Byte[] bKey = new Byte[16];
+            Byte[] Iv = new Byte[16];
+            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
+            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(Iv.Length)), Iv, Iv.Length);
+
+            MemoryStream mStream = new MemoryStream(encryptedByte);
+            RijndaelManaged aes = new RijndaelManaged();
+            aes.Padding = PaddingMode.PKCS7;
+            aes.Mode = CipherMode.CBC;
+            aes.BlockSize = 128;
+            aes.KeySize = 128;
+            aes.Key = bKey;
+            aes.IV = Iv;
+            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
+            try
+            {
+                byte[] tmp = new byte[encryptedByte.Length];
+                int len = cryptoStream.Read(tmp, 0, encryptedByte.Length);
+                byte[] ret = new byte[len];
+                Array.Copy(tmp, 0, ret, 0, len);
+                return Encoding.UTF8.GetString(ret);
+            }
+            finally
+            {
+                cryptoStream.Close();
+                mStream.Close();
+                aes.Clear();
+            }
+        }
+
+

+ 10 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/java回调解密.txt

@@ -0,0 +1,10 @@
+public static byte[] decodeBytes(String str) {
+		byte[] bytes = new byte[str.length() / 2];
+		for (int i = 0; i < str.length(); i += 2) {
+			char c = str.charAt(i);
+			bytes[i / 2] = (byte) ((c - 'a') << 4);
+			c = str.charAt(i + 1);
+			bytes[i / 2] += (c - 'a');
+		}
+		return bytes;
+	}

+ 24 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【2】回调解密Demo/php回调示例.txt

@@ -0,0 +1,24 @@
+<?php
+	$public_key = "";//公钥
+	$secretKey = "";//AES秘钥
+	$vector = "";//加密向量
+	$content = '{"data":"1oblecdinlapfbjjfbpnbipgkedbkknbghifnlfdkfdfpiaidllfnoojcpcmelndajgcgcibcakdpofcamgbnkelaafndajfbafecllcghiecmfmolfnmliejghojjbhkeeclglnkkeekonofnofcbfmgkdcgcadd","signature":"MCwCFB5J0dohkNzqV5fol/Lz8fz5HBD3AhRFoBE3QK6ZnK5scjeOLW3YYh7AKA=="}';
+	$req =callback($content);
+	echo "<pre>";
+	print_r($req); 
+	//解密回调
+	public function callback($content){
+		$request = json_decode($content,true);
+		$public_key='-----BEGIN PUBLIC KEY-----'.PHP_EOL.wordwrap($public_key, 64, "\n", true) .PHP_EOL.'-----END PUBLIC KEY-----';
+		$res=  openssl_get_publickey($public_key);
+		$ok = (bool)openssl_verify($request['data'], base64_decode($request['signature']), $res);
+		openssl_free_key($res); 
+		if(!$ok){
+			return false;
+		}
+		$code = AES::decrypt($request['data'],$secretKey,$vector);
+		return $code;
+	}
+
+
+?>

+ 128 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【3】回调Demo(明文)/.net&C#回调示例.txt

@@ -0,0 +1,128 @@
+public partial class TYLL : System.Web.UI.Page
+    {
+
+        public Dictionary<string, string> Dic
+        {
+            get
+            {
+                var dicCode = new Dictionary<string, string>();
+                dicCode["00000"] = "客户下单成功/订购成功";
+                dicCode["10229"] = "订购中";
+                dicCode["10001"] = "空号/号码不存在";
+                dicCode["10010"] = "欠费/停机";
+                dicCode["10012"] = "号码已冻结或注销";
+                dicCode["10013"] = "黑名单客户";
+                dicCode["10018"] = "不能重复订购";
+                dicCode["10024"] = "业务互斥";
+                dicCode["10033"] = "在途工单";
+                dicCode["10057"] = "号码归属地信息不正确";
+                dicCode["10058"] = "客户业务受限";
+                dicCode["10063"] = "用户状态异常";
+                dicCode["10074"] = "用户信息不存在";
+                dicCode["10225"] = "无主套餐";
+                dicCode["80004"] = "解析接收报文异常";
+                dicCode["90001"] = "系统异常";
+                dicCode["90003"] = "模拟异常报竣";
+                dicCode["10003"] = "非法参数";
+                dicCode["10006"] = "非法客户";
+                dicCode["10007"] = "非法销售品";
+                dicCode["10008"] = "非法请求流水号";
+                dicCode["10030"] = "非法合同编号";
+                dicCode["10031"] = "销售品未配置";
+                dicCode["10040"] = "服务无权访问";
+                dicCode["10054"] = "销售品配置异常";
+                dicCode["10081"] = "销售品不存在";
+                dicCode["10091"] = "回调地址未配置";
+                dicCode["10109"] = "活动省份不存在";
+                dicCode["10230"] = "重复请求流水号";
+                dicCode["10236"] = "无订购记录,重发失败";
+                dicCode["10237"] = "订购已成功,无需重发";
+                dicCode["80002"] = "网络异常";
+                dicCode["99999"] = "系统未知错误";
+                dicCode["10026"] = "合同授权金额不足";
+                dicCode["10028"] = "合同尚未开始";
+                dicCode["10029"] = "合同已经过期";
+
+                return dicCode;
+            }
+        }
+
+        protected void Page_Load(object sender, EventArgs e)
+        {
+            try
+            {
+               
+                var requeststr = "";
+                if (Request.HttpMethod.Equals("POST"))
+                {
+                    var reader = new StreamReader(Request.InputStream);
+                    requeststr = HttpUtility.UrlDecode(reader.ReadToEnd());
+                }
+                else
+                {
+                    requeststr = Request.QueryString.ToString();
+                }
+                //日志记录 requeststr 
+
+                if (string.IsNullOrEmpty(requeststr))
+                {
+                   //日志记录 "空参数"
+                    return;
+                }
+
+                var param = requeststr.FromJson<Dictionary<string, string>>();
+
+                var data = param["data"];
+                var signature = param["signature"];
+
+				var aesKey = getAesKey();	//获取AES密钥
+				var iv = getIv();		//获取向量
+				var dsaKey = getDsaKey();	//获取DSA密钥												
+
+				if (!DSA.verify(data, dsaKey, signature))	//签名校验
+				{
+				   //日志记录  "校验不通过"
+					return;
+				} 
+				var json = AES.decrypt(json.getString("data"), aesKey, iv);	//解密
+				var param2 = json.FromJson<Dictionary<string, string>>();
+				var requestNo = param2["request_no"];
+				var resultCode = param2["result_code"];
+				
+				var item = getOrder(requestNo);	//查询订单号为requestNo的订单
+				
+                if (item == null)
+                {
+                   //日志记录  requestNo + "回调通知订单不存在");
+                    return;
+                }
+
+                if (item.OrderItemStatus != OrderItemStatusEnum.StartCharge && item.OrderItemStatus != OrderItemStatusEnum.Recharge)
+                {
+                     //日志记录  requestNo + "订单已处理");
+                    return;
+                }               
+                switch (resultCode)
+                {
+                    case "00000":
+                        item.SuccessMe();
+                        break;
+                    default:
+                        var msg = "";
+                        Dic.TryGetValue(resultCode, out msg);
+                        item.FailedMe(msg);
+                        break;
+                }
+
+                Response.Write("1");//回调确认
+
+            }
+            catch (Exception ex)
+            {
+                Response.Write("回调异常");
+                //日志记录    回调异常 
+            }
+        }
+    }
+
+}

+ 42 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【3】回调Demo(明文)/java回调示例.txt

@@ -0,0 +1,42 @@
+public static JSONObject getJSONByRequest(HttpServletRequest request) {
+		
+		BufferedReader br = null;
+		StringBuffer sb = new StringBuffer();
+		try {
+			br = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));
+			String line = null;
+			while ((line = br.readLine()) != null) {
+				sb.append(line);
+			}
+			log.info("JSON Request="+sb.toString());
+			JSONObject json = JSONObject.fromObject(sb.toString());
+			if (StringUtil.isEmpty(json.getString("data"))|| StringUtil.isEmpty(json.getString("signature"))){
+				return null;
+			}
+			String aesKey = getAesKey();	//获取AES密钥
+			String iv = getIv();		//获取向量
+			String dsaKey = getDsaKey();	//获取DSA密钥
+			
+			if (!DSA.verify(json.getString("data"), dsaKey, json.getString("signature"))) {	//签名校验
+				log.error("签名校验不通过");
+				return null;
+			}
+			String text = AES.decrypt(json.getString("data"), aesKey, iv);	//解密
+			if (text == null){
+				log.error("解密失败");
+				return null;
+			}
+			return text;
+		} catch (Exception e) {
+			log.error("parseJson io exception " + e.getMessage(), e);
+		} finally {
+			if (br != null) {
+				try {
+					br.close();
+				} catch (IOException e) {
+					log.error("parseJson io finally exception " + e.getMessage(),e);
+				}
+			}
+		}
+		return null;
+	} 

+ 48 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【4】签名校验模板及公钥/Java DSA校验模板.java

@@ -0,0 +1,48 @@
+package com._21cn.fbmp.common.util;
+
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.spec.X509EncodedKeySpec;
+
+import sun.misc.BASE64Decoder;
+
+public class DSA {
+	
+	public static final String KEY_ALGORITHM = "DSA";
+	public static final String SIGNATURE_ALGORITHM = "DSA";
+	
+	/**
+	 * 校验数字签名
+	 * @param text 摘要
+	 * @param publicKey 公钥(签名密钥)
+	 * @param sign 数字签名
+	 * @return
+	 * @throws Exception
+	 */
+	public static boolean verify(String text, String publicKey, String sign) throws Exception {
+		byte[] data = text.getBytes();
+		byte[] keyBytes = decryptBASE64(publicKey); 
+		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
+		PublicKey pubKey = keyFactory.generatePublic(keySpec);
+		
+		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);   
+        signature.initVerify(pubKey); 
+        signature.update(data);
+        
+        return signature.verify(decryptBASE64(sign)); //验证签名
+	}
+	
+	/**
+	 * BASE64Decoder 解密
+	 * @param data 要解密的字符串
+	 * @return 解密后的byte[]
+	 * @throws Exception 
+	 */
+	private static byte[] decryptBASE64(String data) throws Exception {
+		BASE64Decoder decoder = new BASE64Decoder();
+		byte[] buffer = decoder.decodeBuffer(data);
+		return buffer;
+	}
+}

+ 7 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/【2.接口开发用】联调Demo/【4】签名校验模板及公钥/回调参数签名校验公钥.txt

@@ -0,0 +1,7 @@
+校验公钥(正式环境与测试环境相同,请保存好):
+MIIBITCByAYHKoZIzjgEATCBvAJRAMkRGzB6IwsAH4y5HPHKBs4FdroVYilUSI5wMl3KUvMfM6Px
+zK+w8VfSy/ve6PAKIzQxDjKw45GeWf1W3VaVRGphK1PT9ytm67eirycyFVDjAhUAm2DlRf+2Yije
+cGTfZLcvXSsrEIMCUFoyNIHNNMi+zKZS1r+ZwqmBXNU/n95c24iH0WWYsQmQ0hv+SCIQupvaaO6D
+2FzeI62+RbDbyia+WDKLiQcQSKqbwhMwAzlCLyMqcvQRzbgmA1QAAlEAo7A/w25/gARfex0DeDst
+8lcteX3gRuMhqJEjpz1t5F2/Iu+0yOKAuGOzaSC3frY3kLrLTlCT4HtCB5cr3LptO9m+p2XIYv+q
+GETmxxRNKl0=

BIN
helper/refill/api/xyz/tianyi/800系统接口文档/【3.申请参数用】BMS合同参数配置申请操作指引.pdf


BIN
helper/refill/api/xyz/tianyi/800系统接口文档/【4.测试订购失败时看】合作方接口联调常见问题处理指引-2018.7.xlsx


+ 13 - 0
helper/refill/api/xyz/tianyi/800系统接口文档/平台下单地址及出口IP.txt

@@ -0,0 +1,13 @@
+【下单订购接口-正式/测试】
+http://win800.21cn.com/adapter/v1/remote/numberRecognitionUniversal.do(正式)
+https://testapi.800.21cn.com/fps/flowService.do(测试)
+
+【订单查询接口-正式】
+https://api.800.21cn.com/adapter/v1/remote/numberRecognitionCheck.do
+
+【合同余额查询接口】
+http://api.800.21cn.com/fps/queryChargeBalance.do
+
+【我司出口IP】
+42.123.76.4 
+42.123.77.153

BIN
helper/refill/api/xyz/tianyi/800系统接口文档/综合平台订购接口错误编码表及处理建议_2021.11.xlsx


+ 68 - 0
helper/refill/api/xyz/tianyi/RefillCallBack.php

@@ -0,0 +1,68 @@
+<?php
+namespace refill\tianyi;
+
+require_once(BASE_HELPER_RAPI_PATH . '/tianyi/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;
+        }
+    }
+
+    private function sign($params)
+    {
+        ksort($params);
+
+        $content = '';
+        $secret = config::APP_SECRET;
+        foreach ($params as $key => $value) {
+            if($this->check_empty($value) === false) {
+                $content .= "{$key}{$value}";
+            }
+        }
+        $content .= $secret;
+        return md5(urlencode($content));
+    }
+
+    protected function check_empty($value)
+    {
+        if (!isset($value))
+            return true;
+        if ($value === null)
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    public function notify($params)
+    {
+        $status = intval($params['orderStatus']);
+        $order_sn = $params['channelOrderNo'];
+        $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 === 4) {
+            return [$order_id, true, false,true];
+        }
+        elseif ($status === 5) {
+            return [$order_id, false, true,true];
+        }
+        else {
+            return [$order_id, false, false,false];
+        }
+    }
+}

+ 166 - 0
helper/refill/api/xyz/tianyi/RefillPhone.php

@@ -0,0 +1,166 @@
+<?php
+
+namespace refill\tianyi;
+
+require_once(BASE_HELPER_RAPI_PATH . '/tianyi/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillThird
+{
+    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];
+
+        $store_id = $this->mStoreID;
+        $pcode = $other['product_code'];
+        $thrid_refill = Model('thrid_refill');
+        $product = $thrid_refill->getProviderProduct($store_id, $goods_id, $pcode);
+        if (empty($product)) {
+            Log::record("cannot find provider's produce where name={$this->mName}, goods_id = {$goods_id} pcode={$pcode}", Log::ERR);
+            return [0, 0];
+        } else {
+            return [$goods_id, ncPriceFormat($product['channel_amount'])];
+        }
+    }
+
+    private function getProduct($product_code)
+    {
+        $thrid_refill = Model('thrid_refill');
+        return $thrid_refill->getProduct(['system_code' => $product_code,'opened' => 1]);
+    }
+
+    private function req_params(int $phone, string $order_sn)
+    {
+        $params['partner_no'] = config::PARTNER_NO;
+        $params['request_no'] = $order_sn;
+
+        $params['service_code'] = config::service_code;
+        $params['contract_id'] = config::contract_id;
+        $params['activity_id'] = config::activity_id;
+
+        $params['order_type'] = 1;
+        $params['phone_id'] = $phone;
+
+        $params['plat_offer_id'] = '104365';
+
+        $params['effect_type'] = 0;
+        return $params;
+    }
+
+    public function add($card_no, $card_type, $amount, $input, &$net_errno = 0)
+    {
+        $order_sn = $input['order_sn'];
+
+        $code = $this->req_params($card_no, $order_sn);
+        $params['partner_no'] = config::PARTNER_NO;
+        $params['code'] = config::encrypt(json_encode($code));
+
+        $params = json_encode($params);
+        $resp = http_post_data(config::ORDER_URL, $params , config::ExtHeaders, $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['result_code'] == '00000') {
+                return [true, $resp['request_no'], false];
+            } else {
+                return [false, $resp['result_code'], false];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['partner_no'] = config::PARTNER_NO;
+        $params['orderNo'] = $refill_info['ch_trade_no'];
+        $params['timestamp'] = time();
+        $params['sign'] = $this->sign($params);
+
+        $resp = http_request(config::QUERY_URL, $params, 'GET', false, []);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            }
+            elseif($resp['resultCode'] == 1000)
+            {
+                $status = intval($resp['order']['orderStatus']);
+                if ($status === 4) {
+                    $order_state = ORDER_STATE_SUCCESS;
+                } elseif (in_array($status, [2,5])) {
+                    $order_state = ORDER_STATE_CANCEL;
+                } elseif (in_array($status, [0,1,3])) {
+                    $order_state = ORDER_STATE_SEND;
+                } else {
+                    return [false, $resp['resultReason']];
+                }
+                return [true, $order_state];
+            }
+            else
+            {
+                return [false, $resp['resultReason']];
+            }
+
+        }
+    }
+
+    public function balance()
+    {
+        $params['appkey'] = config::APP_KEY;
+        $params['timestamp'] = time();
+        $params['sign'] = $this->sign($params);
+
+        $resp = http_request(config::BALANCE_URL, $params, 'GET', false, [], $net_errno);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '网络错误'];
+            } elseif ($resp['resultCode'] == 1000) {
+                return [true, $resp['balance']];
+            } else {
+                return [false, $resp['resultReason']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        ksort($params);
+
+        $content = '';
+        $secret = config::APP_SECRET;
+        foreach ($params as $key => $value) {
+            if($this->check_empty($value) === false) {
+                $content .= "{$key}{$value}";
+            }
+        }
+        $content .= $secret;
+        return md5(urlencode($content));
+    }
+}

+ 6 - 0
helper/refill/api/xyz/tianyi/account.txt

@@ -0,0 +1,6 @@
+https://800.189.cn/bms
+13916932570
+帐号是:bjqdw
+初始密码:V7y8%Y60
+
+服务编码:FS0001

+ 68 - 0
helper/refill/api/xyz/tianyi/config.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace refill\tianyi;
+
+class config
+{
+    const ORDER_URL = 'https://api.800.21cn.com/adapter/v1/remote/numberRecognitionUniversal.do';
+    const QUERY_URL = 'https://api.800.21cn.com/adapter/v1/remote/numberRecognitionCheck.do';
+    const BALANCE_URL = 'http://api.800.21cn.com/fps/queryChargeBalance.do';
+
+    const PARTNER_NO = '105277719';
+    const SECRET_KEY = 'USAJuw0zJkmqM0yA';
+    const IV = '2859900876319125';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_santi.php";
+    const ExtHeaders = ['Content-Type: application/json;charset=UTF-8'];
+
+    const contract_id = '103657';
+    const activity_id = '107256';
+    const service_code = 'FS0001';
+
+    const Products =
+        [
+        ];
+
+
+    private static function decodeBytes($hex)
+    {
+        $str = '';
+        for($i=0;$i<strlen($hex);$i+=2){
+            $tmpValue = (((ord($hex[$i]) - ord('a')) & 0xf ) <<4) + ((ord($hex[$i+1])- ord('a')) & 0xf);
+            $str .= chr($tmpValue);
+        }
+        return  $str;
+    }
+
+    private static function encodeBytes($string)
+    {
+        $str = '';
+        for($i=0;$i<strlen($string);$i++)
+        {
+            $tmpValue = ord($string[$i]);
+            $ch = ($tmpValue >> 4 & 0xf) + ord('a');
+            $str .= chr($ch);
+            $ch = ($tmpValue & 0xf) + ord('a');
+            $str .= chr($ch);
+        }
+        return $str;
+    }
+    /**
+     * 加密数据
+     * @param String $encryptedText 待加密密文
+     * @return String
+     */
+    public static function encrypt(string $encryptedText) {
+
+        $ciphertext = openssl_encrypt($encryptedText, "AES-128-CBC", self::SECRET_KEY, OPENSSL_RAW_DATA, self::IV);
+        return self::encodeBytes($ciphertext);
+    }
+    /**
+     * 解密数据
+     * @param String $encryptedText 待解密数据
+     * @return String
+     */
+    public static function decrypt(string $encryptedText) {
+        $encryptedText = self::decodeBytes($encryptedText);
+        return openssl_decrypt($encryptedText, "AES-128-CBC", self::SECRET_KEY, OPENSSL_RAW_DATA, self::IV);
+    }
+}

BIN
helper/refill/api/xyz/tianyi/北京趣带娃科技有限公司正式合同参数.xlsx


+ 3 - 1
helper/refill/api/xyz/weixue/config.php

@@ -39,6 +39,8 @@ class config
                 50  => '101706',
                 100 => '101707',
                 200 => '101708',
+                300 => '101709',
+                500 => '101710'
             ],
     ];
-}
+}

+ 4 - 0
helper/refill/api/xyz/weixue/对接文档-yezi.txt

@@ -27,3 +27,7 @@ ID:10002703
 101706 全国联通话费50元直充
 101707 全国联通话费100元直充
 101708 全国联通话费200元直充
+
+2022.9.14
+101709    300面值编码
+101710     500面值编码

+ 4 - 2
helper/refill/api/xyz/xinruiheng/config.php

@@ -37,7 +37,9 @@ class config
                 30  => '101705',
                 50  => '101706',
                 100 => '101707',
-                200 => '101708'
+                200 => '101708',
+                300 => '101709',
+                500 => '101710',
             ],
         mtopcard\ChinaTelecomCard =>
             [
@@ -47,4 +49,4 @@ class config
                 200 => '101726',
             ]
     ];
-}
+}

+ 5 - 1
helper/refill/api/xyz/xinruiheng/对接文档-yezi.txt

@@ -28,4 +28,8 @@ http://www.firstsup.net/showdoc
 全国电信话费30元直充         101723
 全国电信话费50元直充         101724
 全国电信话费100元直充        101725
-全国电信话费200元直充        101726
+全国电信话费200元直充        101726
+
+20220915
+300编码   101709
+500编码   101710

+ 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);
     }
-}
+}

+ 55 - 0
helper/refill/api/xyz/yingdian_hf/RefillCallBack.php

@@ -0,0 +1,55 @@
+<?php
+namespace refill\yingdian_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yingdian_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;
+        }
+    }
+
+    private function sign($params)
+    {
+        unset($params['proof']);
+        $content = '';
+        ksort($params);
+        foreach ($params as $key => $val){
+            $content .= "{$key}=". urlencode($val) ."&";
+        }
+        $content .= "key=".config::KEY;
+
+        return md5($content);
+    }
+
+    public function notify($params)
+    {
+        $status = $params['state'];
+        $order_sn = $params['outTradeNo'];
+        $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') {
+            Model('refill_order')->edit($order_id, ['official_sn' => $params['proof'], 'ch_trade_no' => $params['orderNo']]);
+            return [$order_id, true, false, true];
+        } elseif ($status === 'FAIL') {
+            Model('refill_order')->edit($order_id, ['ch_trade_no' => $params['orderNo']]);
+            return [$order_id, false, true, true];
+        } else {
+            return [$order_id, false, false, false];
+        }
+    }
+}

+ 140 - 0
helper/refill/api/xyz/yingdian_hf/RefillPhone.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace refill\yingdian_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yingdian_hf/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $card_no, int $card_type, string $order_sn, int $amount)
+    {
+        $params['merchantId'] = config::MCH_ID;
+        $params['cardNo'] = $card_no;
+        $params['amount'] = $amount;
+        $params['outTradeNo'] = $order_sn;
+        $params['requestTime'] = $this->getMillisecond();
+        $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, $card_type, $params['order_sn'], $amount);
+        $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 = json_decode($resp, true);
+            if (empty($resp)) {
+                return [false, '系统错误', true];
+            } elseif ($resp['code'] === 200) {
+                return [true, '', false];
+            } else {
+                return [false, $resp['msg'], false];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['type'] = 'query';
+        $params['merchantId'] = config::MCH_ID;
+        $params['outTradeNo'] = $refill_info['order_sn'];
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::QUERY_URL, $params);
+        if (empty($resp)) {
+            return [false, '系统错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp))
+            {
+                return [false, '系统错误'];
+            }
+            elseif ($resp['code'] === 200)
+            {
+                $update['ch_trade_no'] = $resp['data']['orderNo'];
+                $status = $resp['data']['state'];
+                if ($status === 'SUCCESS') {
+                    $update['official_sn'] = $resp['data']['proof'];
+                    $order_state = ORDER_STATE_SUCCESS;
+                } elseif ($status === 'FAIL') {
+                    $order_state = ORDER_STATE_CANCEL;
+                } elseif ($status === 'PENDING') {
+                    $order_state = ORDER_STATE_SEND;
+                } else {
+                    return [false, $status];
+                }
+                Model('refill_order')->edit($refill_info['order_id'], $update);
+
+                return [true, $order_state];
+            }
+            elseif ($resp['code'] === 207 && (time() - $refill_info['commit_time'] >= 300)) {
+                $order_state = ORDER_STATE_NOEXIST;
+                return [true, $order_state];
+            }
+            else {
+                return [false, $resp['msg']];
+            }
+        }
+    }
+
+    public function balance()
+    {
+        $params['type'] = 'balance';
+        $params['merchantId'] = config::MCH_ID;
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::BALANCE_URL, $params);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        } else {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if ($resp['code'] === 200) {
+                return [true, $resp['data']['balance']];
+            } else {
+                return [false, $resp['msg']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        $content = '';
+        ksort($params);
+        foreach ($params as $key => $val){
+            $content .= "{$key}=". urlencode($val) ."&";
+        }
+        $content .= "key=".config::KEY;
+
+        return md5($content);
+    }
+
+    private function getMillisecond()
+    {
+        $cur = microtime (true);
+        return intval($cur * 1000);
+    }
+}

+ 16 - 0
helper/refill/api/xyz/yingdian_hf/config.php

@@ -0,0 +1,16 @@
+<?php
+namespace refill\yingdian_hf;
+
+class config
+{
+    //https://www.showdoc.com.cn/1946422946762386/8847941177523161
+    const ORDER_URL = 'https://yd.khuo.net/api/merchant/recharge/phone';
+    const QUERY_URL = 'https://yd.khuo.net/api/merchant/recharge/queryOrder';
+    const BALANCE_URL = 'https://yd.khuo.net/api/merchant/recharge/queryBalance';
+
+    const MCH_ID = '10026';
+    const KEY = '0c0bc7069f2e4814a9b5a66bb3cbffc8';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_yingdian_hf.php";
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
+
+}

+ 3 - 0
helper/refill/api/xyz/yingdian_hf/对接文档.txt

@@ -0,0 +1,3 @@
+商户号 10026
+秘钥 0c0bc7069f2e4814a9b5a66bb3cbffc8
+https://www.showdoc.com.cn/1946422946762386/8847941177523161

+ 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,
+        ]
+    ];
+}

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

@@ -64,10 +64,10 @@ class config
     const Price = [
         //移动
         "4-10-2" => 10.15, "4-20-2" => 19.92, "4-30-2" => 29.94, "4-50-2" => 49.9, "4-100-2" => 99.8, "4-200-2" => 199.6, "4-300-2" => 299.4, "4-500-2" => 499,//天津 2
-        "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-6" => 9.81, "4-20-6" => 19.62, "4-30-6" => 29.43, "4-50-6" => 49.05, "4-100-6" => 98.1, "4-200-6" => 196.2, "4-300-6" => 294.3, "4-500-6" => 490.5,//辽宁 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.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-29" => 9.835, "4-20-29" => 19.67, "4-30-29" => 29.505, "4-50-29" => 49.175, "4-100-29" => 98.35, "4-200-29" => 196.7, "4-300-29" => 295.05, "4-500-29" => 491.75,//青海 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

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

@@ -39,6 +39,8 @@ class config
                 50  => '101706',
                 100 => '101707',
                 200 => '101708',
+                300 => '101709',
+                500 => '101710'
             ],
     ];
 }

+ 4 - 2
helper/refill/api/yl/xinruiheng/config.php

@@ -37,7 +37,9 @@ class config
                 30  => '101705',
                 50  => '101706',
                 100 => '101707',
-                200 => '101708'
+                200 => '101708',
+                300 => '101709',
+                500 => '101710',
             ],
         mtopcard\ChinaTelecomCard =>
             [
@@ -47,4 +49,4 @@ class config
                 200 => '101726',
             ]
     ];
-}
+}

+ 55 - 0
helper/refill/api/yl/yingdian_hf/RefillCallBack.php

@@ -0,0 +1,55 @@
+<?php
+namespace refill\yingdian_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yingdian_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;
+        }
+    }
+
+    private function sign($params)
+    {
+        unset($params['proof']);
+        $content = '';
+        ksort($params);
+        foreach ($params as $key => $val){
+            $content .= "{$key}=". urlencode($val) ."&";
+        }
+        $content .= "key=".config::KEY;
+
+        return md5($content);
+    }
+
+    public function notify($params)
+    {
+        $status = $params['state'];
+        $order_sn = $params['outTradeNo'];
+        $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') {
+            Model('refill_order')->edit($order_id, ['official_sn' => $params['proof'], 'ch_trade_no' => $params['orderNo']]);
+            return [$order_id, true, false, true];
+        } elseif ($status === 'FAIL') {
+            Model('refill_order')->edit($order_id, ['ch_trade_no' => $params['orderNo']]);
+            return [$order_id, false, true, true];
+        } else {
+            return [$order_id, false, false, false];
+        }
+    }
+}

+ 140 - 0
helper/refill/api/yl/yingdian_hf/RefillPhone.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace refill\yingdian_hf;
+
+require_once(BASE_HELPER_RAPI_PATH . '/yingdian_hf/config.php');
+
+use refill;
+use Log;
+
+class RefillPhone extends refill\IRefillPhone
+{
+    public function __construct($cfgs)
+    {
+        parent::__construct($cfgs);
+    }
+
+    private function req_params(int $card_no, int $card_type, string $order_sn, int $amount)
+    {
+        $params['merchantId'] = config::MCH_ID;
+        $params['cardNo'] = $card_no;
+        $params['amount'] = $amount;
+        $params['outTradeNo'] = $order_sn;
+        $params['requestTime'] = $this->getMillisecond();
+        $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, $card_type, $params['order_sn'], $amount);
+        $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 = json_decode($resp ,true);
+            if (empty($resp)) {
+                return [false, '系统错误', true];
+            } elseif ($resp['code'] === 200) {
+                return [true, '', false];
+            } else {
+                return [false, $resp['msg'], false];
+            }
+        }
+    }
+
+    public function query($refill_info)
+    {
+        $params['type'] = 'query';
+        $params['merchantId'] = config::MCH_ID;
+        $params['outTradeNo'] = $refill_info['order_sn'];
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::QUERY_URL, $params);
+        if (empty($resp)) {
+            return [false, '系统错误'];
+        }
+        else
+        {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if (empty($resp))
+            {
+                return [false, '系统错误'];
+            }
+            elseif ($resp['code'] === 200)
+            {
+                $update['ch_trade_no'] = $resp['data']['orderNo'];
+                $status = $resp['data']['state'];
+                if ($status === 'SUCCESS') {
+                    $update['official_sn'] = $resp['data']['proof'];
+                    $order_state = ORDER_STATE_SUCCESS;
+                } elseif ($status === 'FAIL') {
+                    $order_state = ORDER_STATE_CANCEL;
+                } elseif ($status === 'PENDING') {
+                    $order_state = ORDER_STATE_SEND;
+                } else {
+                    return [false, $status];
+                }
+                Model('refill_order')->edit($refill_info['order_id'], $update);
+
+                return [true, $order_state];
+            }
+            elseif ($resp['code'] === 207 && (time() - $refill_info['commit_time'] >= 300)) {
+                $order_state = ORDER_STATE_NOEXIST;
+                return [true, $order_state];
+            }
+            else {
+                return [false, $resp['msg']];
+            }
+        }
+    }
+
+    public function balance()
+    {
+        $params['type'] = 'balance';
+        $params['merchantId'] = config::MCH_ID;
+        $sign = $this->sign($params);
+        $params['sign'] = $sign;
+
+        $resp = http_request(config::BALANCE_URL, $params);
+
+        if (empty($resp)) {
+            return [false, '网络错误'];
+        } else {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if ($resp['code'] === 200) {
+                return [true, $resp['data']['balance']];
+            } else {
+                return [false, $resp['msg']];
+            }
+        }
+    }
+
+    private function sign($params)
+    {
+        $content = '';
+        ksort($params);
+        foreach ($params as $key => $val){
+            $content .= "{$key}=". urlencode($val) ."&";
+        }
+        $content .= "key=".config::KEY;
+
+        return md5($content);
+    }
+
+    private function getMillisecond()
+    {
+        $cur = microtime (true);
+        return intval($cur * 1000);
+    }
+}

+ 16 - 0
helper/refill/api/yl/yingdian_hf/config.php

@@ -0,0 +1,16 @@
+<?php
+namespace refill\yingdian_hf;
+
+class config
+{
+    //https://www.showdoc.com.cn/1946422946762386/8847941177523161
+    const ORDER_URL = 'https://yd.khuo.net/api/merchant/recharge/phone';
+    const QUERY_URL = 'https://yd.khuo.net/api/merchant/recharge/queryOrder';
+    const BALANCE_URL = 'https://yd.khuo.net/api/merchant/recharge/queryBalance';
+
+    const MCH_ID = '10025';
+    const KEY = '4bebe17dcbde4889957cb0752f09f77a';
+    const NOTIFY_URL = BASE_SITE_URL . "/mobile/callback/refill_yingdian_hf.php";
+    const ExtHeaders = ['Content-Type:application/x-www-form-urlencoded;charset=utf-8'];
+
+}

+ 3 - 0
helper/refill/api/yl/yingdian_hf/对接文档.txt

@@ -0,0 +1,3 @@
+商户号 10025
+秘钥 4bebe17dcbde4889957cb0752f09f77a
+https://www.showdoc.com.cn/1946422946762386/8847941177523161

+ 4 - 0
mobile/callback/refill_dazhanggui_high.php

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

+ 4 - 0
mobile/callback/refill_yingdian_hf.php

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

+ 2 - 1
plot/refill/ChannelCovSuccPainter.py

@@ -76,8 +76,9 @@ class ChannelCovSuccPainter(ChannelPainter):
             ax.set_xticklabels(lables)
             fig.autofmt_xdate()
             ax.grid()
-            fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
+            # fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
             ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
+            fig.tight_layout()
 
             buf = BytesIO()
             fig.savefig(buf, format="png")

+ 2 - 1
plot/refill/ChannelPainter.py

@@ -76,8 +76,9 @@ class ChannelPainter(PainterBase):
             ax.set_xticklabels(lables)
             fig.autofmt_xdate()
             ax.grid()
-            fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
+            # fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
             ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
+            fig.tight_layout()
 
             buf = BytesIO()
             fig.savefig(buf, format="png")

+ 15 - 14
plot/refill/MerchantAmountPainter.py

@@ -1,6 +1,6 @@
 from .DataStream import EMchPosmap as pos_map, span_days, time_border, calc_interval
 from .MerchantReader import MerchantReader
-from .MerchantPainter import MerchantPainter, allpathes
+from .MerchantPainter import MerchantPainter, mch_paths
 from matplotlib.figure import Figure
 from matplotlib import ticker
 from io import BytesIO
@@ -44,16 +44,15 @@ class MerchantAmountPainter(MerchantPainter):
             ax.grid()
 
         def flush(fig):
-            fig.autofmt_xdate()
+            fig.tight_layout()
             buf = BytesIO()
             fig.savefig(buf, format="png")
             return buf
-
         return create, end,flush
 
     def paint(self):
-        tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types, self._spec)
-        gen = allpathes(self._reader, tuple_pathes, self._days, self._spec)
+        tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types)
+        gen = mch_paths(self._reader, tuple_pathes, self._days)
         if len(self._days) == 0:
             return BytesIO()
 
@@ -91,10 +90,11 @@ class MerchantAmountPainter(MerchantPainter):
         rect_succ = ax.bar(x_asix + width * 0.5, list(succ_count), width, label='succ',align='center')
         rect_fail = ax.bar(x_asix + width * 1.5, list(fail_count), width, label='fail', align='center')
 
-        ax.bar_label(rect_send, padding=0, rotation=270, fmt='%d')
-        ax.bar_label(rect_submit, padding=0, rotation=270, fmt='%d')
-        ax.bar_label(rect_succ, padding=0, rotation=270, fmt='%d')
-        ax.bar_label(rect_fail, padding=0, rotation=270, fmt='%d')
+        alpha = 45
+        ax.bar_label(rect_send, padding=0, rotation=alpha, fmt='%d')
+        ax.bar_label(rect_submit, padding=0, rotation=alpha, fmt='%d')
+        ax.bar_label(rect_succ, padding=0, rotation=alpha, fmt='%d')
+        ax.bar_label(rect_fail, padding=0, rotation=alpha, fmt='%d')
 
         fig_end(ax, xticks=x_asix, xlables=lables)
         pass
@@ -109,11 +109,12 @@ class MerchantAmountPainter(MerchantPainter):
         rect_succ = ax.bar(x_asix + width, list(succ_amount), width, label='succ',align='center')
         rect_fail = ax.bar(x_asix + width * 2, list(fail_amount), width, label='fail', align='center')
 
-        ax.bar_label(rect_submit, padding=0, rotation=270, fmt='%.2f')
-        ax.bar_label(rect_send, padding=0, rotation=270, fmt='%.2f')
-        ax.bar_label(rect_msucc, padding=0, rotation=270, fmt='%.2f')
-        ax.bar_label(rect_succ, padding=0, rotation=270, fmt='%.2f')
-        ax.bar_label(rect_fail, padding=0, rotation=270, fmt='%.2f')
+        alpha = 45
+        ax.bar_label(rect_submit, padding=0, rotation=alpha, fmt='%.2f')
+        ax.bar_label(rect_send, padding=0, rotation=alpha, fmt='%.2f')
+        ax.bar_label(rect_msucc, padding=0, rotation=alpha, fmt='%.2f')
+        ax.bar_label(rect_succ, padding=0, rotation=alpha, fmt='%.2f')
+        ax.bar_label(rect_fail, padding=0, rotation=alpha, fmt='%.2f')
 
         fig_end(ax, xticks=x_asix, xlables=lables)
         pass

+ 15 - 1
plot/refill/MerchantPainter.py

@@ -20,6 +20,19 @@ def add_mchid(mchid):
 def get_mchids():
     return list(_all_mchids)
 
+def mch_paths(reader: MerchantReader, tuple_pathes: dict, days: list):
+    count = len(days)
+    for mchid, tup in tuple_pathes.items():
+        mch_datas = reader.init_data(count)
+        for _card_type, _spec in tup:
+            for i, day in enumerate(days):
+                data = reader.read(day, mchid, _card_type, _spec)
+                if data is not None:
+                    column_pos = i * 86400
+                    view = mch_datas[:, column_pos:column_pos + 86400]
+                    view += data
+        yield mchid, None, None, mch_datas
+
 def allpathes(reader: MerchantReader, tuple_pathes: dict, days: list, spec=None):
     count = len(days)
     show_detail = True if len(list(tuple_pathes.keys())) == 1 else False
@@ -83,8 +96,9 @@ class MerchantPainter(PainterBase):
 
             fig.autofmt_xdate()
             ax.grid()
-            fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
+            # fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
             ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
+            fig.tight_layout()
 
             buf = BytesIO()
             fig.savefig(buf, format="png")

+ 2 - 1
plot/refill/NetcheckPainter.py

@@ -60,8 +60,9 @@ class NetcheckPainter(PainterBase):
             ax.set_xticklabels(lables)
             fig.autofmt_xdate()
             ax.grid()
-            fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
+            # fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
             ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
+            fig.tight_layout()
 
             buf = BytesIO()
             fig.savefig(buf, format="png")

+ 30 - 22
rdispatcher/proxy.php

@@ -8,14 +8,13 @@ require_once(BASE_HELPER_PATH . '/refill/policy/transfer.php');
 
 class proxy
 {
-    private function onEerror(refill\order $order,$errmsg)
+    private function onEerror(refill\order $order,$need_callback,$errmsg)
     {
         $refill_order = Model('refill_order');
-
         $mchid = $order->mchid();
         $mch_order = $order->mch_order();
-
         $last_order_id = $order->last_order_id();
+
         if ($last_order_id === 0) {
             $order_id = refill\RefillFactory::instance()->zero_order($order, $errmsg);
             $last_order_id = $order_id;
@@ -26,6 +25,17 @@ class proxy
         refill\util::pop_queue_order($mchid, $mch_order);
         QueueClient::push("NotifyMerchantComplete", ['order_id' => $last_order_id, 'manual' => false]);
 
+        if($need_callback)
+        {
+            Log::record("onEerror monitor_callback",Log::DEBUG);
+            $mch_amount = refill\RefillFactory::instance()->mch_amount($order);
+            if($mch_amount == false) {
+                refill\util::monitor_callback($mchid, $order->spec(), $order->card_type(), 0.0, 0, false, $order->order_time());
+            } else {
+                refill\util::monitor_callback($mchid, $order->spec(), $order->card_type(), $mch_amount, 0, false, $order->order_time());
+            }
+        }
+
         return true;
     }
 
@@ -98,9 +108,10 @@ class proxy
     public function add($params)
     {
         $order = refill\order::from_parameters($params);
+        $need_callback = !$order->first_commit();
 
         if($order->is_black()) {
-            return $this->onEerror($order, '黑名单卡号');
+            return $this->onEerror($order, $need_callback,'黑名单卡号');
         }
 
         $mchid = $order->mchid();
@@ -115,13 +126,13 @@ class proxy
 
         if ($this->canceled($mchid, $mch_order)) {
             refill\util::del_cancel_order($mchid,$mch_order);
-            return $this->onEerror($order, '订单被拦截');
+            return $this->onEerror($order, $need_callback,'订单被拦截');
         }
         if (!$order->validate()) {
-            return $this->onEerror($order, '空号或风险号');
+            return $this->onEerror($order, $need_callback,'空号或风险号');
         }
         if($this->need_intercept($order)) {
-            return $this->onEerror($order, '转网,问题号码,运营商维护被拦截.');
+            return $this->onEerror($order, $need_callback,'转网,问题号码,运营商维护被拦截.');
         }
 
         if($this->successed($mchid,$mch_order)) {
@@ -134,29 +145,29 @@ class proxy
         [$org_quality, $quality] = refill\RefillFactory::instance()->find_quality($order, $skip);
         $order->set_quality($org_quality,$quality);
         if($quality == 0) {
-            return $this->onEerror($order, '找不到合适质量的通道');
+            return $this->onEerror($order, $need_callback,'找不到合适质量的通道');
         }
 
         if($this->region_intercept($order)) {
-            return $this->onEerror($order, '运营商维护被全局拦截.');
+            return $this->onEerror($order, $need_callback,'运营商维护被全局拦截.');
         }
 
         if($order->first_commit())
         {
             if (!$order->match_card_type()) {
-                return $this->onEerror($order, '卡类型和产品类型不符.');
+                return $this->onEerror($order, $need_callback,'卡类型和产品类型不符.');
             }
 
             if(refill\util::merchant_debt_stoped($mchid)) {
                 Log::record("merchant_debt_stoped mchid={$mchid} stoped=1",Log::DEBUG);
-                return $this->onEerror($order, '米不够了.');
+                return $this->onEerror($order, $need_callback,'米不够了.');
             } else {
                 Log::record("merchant_debt_stoped mchid={$mchid} stoped=0",Log::DEBUG);
             }
 
             $mch_amount = refill\RefillFactory::instance()->mch_amount($order);
             if($mch_amount === false) {
-                return $this->onEerror($order, '没有协商商品购买价格.');
+                return $this->onEerror($order, $need_callback,'没有协商商品购买价格.');
             }
             else {
                 refill\util::monitor_submit($order->mchid(), $order->spec(), $order->card_type(), $mch_amount,$order->order_time());
@@ -197,13 +208,8 @@ class proxy
                 $fError = true;
             }
 
-            if($fError)
-            {
-                $mch_amount = refill\RefillFactory::instance()->mch_amount($order);
-                if($mch_amount !== false) {
-                    refill\util::monitor_callback($mchid, $order->spec(), $order->card_type(), $mch_amount, 0, false, $order->order_time());
-                }
-                return $this->onEerror($order, $errmsg);
+            if ($fError) {
+                return $this->onEerror($order,true, $errmsg);
             }
         }
 
@@ -306,8 +312,10 @@ class proxy
         };
 
         $order = refill\order::from_parameters($params);
+        $need_callback = !$order->first_commit();
+
         if($is_closed($order->pcode())) {
-            return $this->onEerror($order, "{$order->pcode()} has closed.");
+            return $this->onEerror($order, $need_callback,"{$order->pcode()} has closed.");
         }
 
         $mchid = $order->mchid();
@@ -319,7 +327,7 @@ class proxy
 
         $mch_amount = refill\RefillFactory::instance()->mch_amount($order);
         if ($mch_amount === false) {
-            return $this->onEerror($order, '没有协商商品购买价格.');
+            return $this->onEerror($order, $need_callback,'没有协商商品购买价格.');
         } else {
             refill\util::monitor_submit($order->mchid(), $order->spec(), $order->card_type(), $mch_amount, $order->order_time());
         }
@@ -330,7 +338,7 @@ class proxy
             if ($errcode === refill\errcode::MERCHANT_REFILL_ERROR && $neterr && refill\util::need_check($net_errno)) {
                 return QueueClient::async_push("QueryOrderNeterr", ['order_id' => $order_id], 15);
             } else {
-                return $this->onEerror($order, $errmsg);
+                return $this->onEerror($order, $need_callback, $errmsg);
             }
         }
 

+ 28 - 0
test/TestRefill.php

@@ -2516,6 +2516,34 @@ class TestRefill extends TestCase
         $resp = $provider->notify($params);
     }
 
+    public function testDazhanggui_high()
+    {
+//        $provider = $this->getProvider('dazhanggui_high');
+//        $resp = $provider->balance();
+//        $resp = $provider->add(15811535608, 4, 50, ['order_sn' => $this->make_sn()]);
+//        $resp = $provider->query(['order_sn' => '97891663034634307994']);
+
+        $body = '{"szOrderId":"97891663034634307994","fSalePrice":"48.75","szAgentId":"200021","nFlag":"3","szVerifyString":"2072991c0760ca1be5ec05ba3f4cf0b0","szPhoneNum":"15811535608","szRtnMsg":"","nDemo":"50"}';
+        $params = json_decode($body, true);
+        $provider = $this->getProvider('dazhanggui_high', 'RefillCallBack');
+        $ret = $provider->verify($params);
+        $resp = $provider->notify($params);
+    }
+
+    public function testYingdian_hf()
+    {
+//        $provider = $this->getProvider('yingdian_hf');
+//        $resp = $provider->balance();
+//        $resp = $provider->add(15811535608, 4, 50, ['order_sn' => $this->make_sn()]);
+//        $resp = $provider->query(['order_sn' => '95361663137380842711']);
+
+        $body = '{"amount":"50.0","cardNo":"15811535608","merchantId":"10026","orderNo":"20220914143618594153","outTradeNo":"95361663137380842711","requestTime":"2022-09-14 14:36:21","sign":"219f2f45298550c52a4a7e3b98b253a7","state":"FAIL"}';
+        $params = json_decode($body, true);
+        $provider = $this->getProvider('yingdian_hf', 'RefillCallBack');
+        $ret = $provider->verify($params);
+        $resp = $provider->notify($params);
+    }
+
     public function testAmingjd()
     {
 //        $provider = new refill\amingjd\RefillPhone([]);

+ 12 - 0
test/TestRefillYl.php

@@ -824,4 +824,16 @@ class TestRefillYl extends TestCase
         $provider = $this->getProvider('weixue');
         $resp = $provider->balance();
     }
+
+    public function testDazhanggui_high()
+    {
+        $provider = $this->getProvider('dazhanggui_high');
+        $resp = $provider->balance();
+    }
+
+    public function testYingdian_hf()
+    {
+        $provider = $this->getProvider('yingdian_hf');
+        $resp = $provider->balance();
+    }
 }

+ 11 - 2
vapi/control/retail.php

@@ -1,4 +1,5 @@
 <?php
+require_once(BASE_ROOT_PATH . '/vapi/control/sapi.php');
 
 class retailControl extends vbaseControl
 {
@@ -33,11 +34,15 @@ class retailControl extends vbaseControl
         if(!empty($retail)) {
             return [false, "此联系电话已申请过."];
         }
+        $id_card = $_POST['id_card'];
+        if (!preg_match('#^\d{17}(\d|X)$#', $id_card)) {
+            return [false, "身份证号格式错误."];
+        }
 
         $insert = [
             'channel_code' => $channel_code, 'province' => $province, 'city' => $city, 'area' => $area,
             'address' => $address, 'applicant_name' => $applicant_name, 'contact_phone' => $contact_phone,
-            'create_time' => time(), 'retail_sn' => $this->make_sn()
+            'id_card' => $id_card, 'create_time' => time(), 'retail_sn' => $this->make_sn()
         ];
         return [true, $insert];
     }
@@ -51,6 +56,10 @@ class retailControl extends vbaseControl
 
         $resp = Model('')->table('retail')->insert($params);
         if ($resp) {
+            $sapi = new sapi();
+            $body = ['pageId' => $_POST['pageId'], 'tid' => $_POST['tid'], 'lbid' => $_POST['lbid']];
+            $resp = $sapi->send($body);
+            Log::record("sapi result {$resp}", Log::DEBUG);
             return self::outsuccess([]);
         } else {
             return self::outerr(301, "录入信息失败.");
@@ -63,4 +72,4 @@ class retailControl extends vbaseControl
             . sprintf('%010d', time())
             . sprintf('%06d', (float)microtime() * 1000000);
     }
-}
+}

+ 51 - 0
vapi/control/sapi.php

@@ -0,0 +1,51 @@
+<?php
+
+require_once(BASE_CORE_PATH . '/framework/function/http.php');
+
+class sapi
+{
+    private $url = 'https://sapi.ads.oppomobile.com/v1/clue/sendData';
+    private $ownerId = '1000178033';
+    private $API_ID = 'cbbf0a225cd44cba81b9b6e093ded0a2';
+    private $APIKEY = '0d10124566ff41c393c0c418a3ae147a';
+
+    private function create_token()
+    {
+        $time = time();
+        $sign = sha1($this->API_ID .$this->APIKEY . $time);
+        return base64_encode($this->ownerId. ','. $this->API_ID. ',' .$time. ',' . $sign);
+    }
+
+    public function send($body)
+    {
+        $params['pageId'] = $body['pageId'];
+        $params['ownerId'] = $this->ownerId;
+        $params['ip'] = $_SERVER['REMOTE_ADDR'];
+        $params['tid'] = $body['tid'];
+        $params['lbid'] = $body['lbid'];
+        $params['transformType'] = 101;
+
+        $token = $this->create_token();
+        $header = [
+            'Content-Type: application/json',
+            "Authorization:Bearer {$token}"
+        ];
+        $params = json_encode($params);
+        Log::record("sapi send json data {$params}", Log::ERR);
+
+        $resp = http_post_data($this->url, $params, $header, $net_errno);
+        if (empty($resp)) {
+            Log::record("sapi send neterr {$net_errno}", Log::ERR);
+            return false;
+        } else {
+            Log::record($resp, Log::DEBUG);
+            $resp = json_decode($resp, true);
+            if ($resp['code'] === 0) {
+                return true;
+            } else {
+                Log::record("sapi send err {$resp['msg']}", Log::ERR);
+                return false;
+            }
+        }
+    }
+}