MobileController.php 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. <?php
  2. namespace app\api\controller;
  3. use addons\epay\library\Service;
  4. use app\common\controller\UserApi;
  5. use app\common\library\MobileConstant;
  6. use app\common\model\AdIndexOrderedFlow;
  7. use app\common\model\Area;
  8. use app\common\model\LogisticsCompany;
  9. use app\common\model\Mobile;
  10. use app\common\model\MobileInfo;
  11. use app\common\model\MobileOrder;
  12. use app\common\model\MobileOrderNo;
  13. use app\common\model\MobileUserHistory;
  14. use app\common\model\Payment;
  15. use app\common\model\SysConfig;
  16. use app\common\service\Jdpay;
  17. use app\common\service\MobileComputer;
  18. use app\common\service\SmsSend;
  19. use app\common\service\TransferCheck;
  20. use app\service\byte_dance\ByteDanceOrderPush;
  21. use app\service\byte_dance\ByteDancePay;
  22. use app\service\byte_dance\OceanEngineService;
  23. use app\service\EsMobileService;
  24. use app\service\GantanhaoService;
  25. use app\service\fast_hand\AccessToken;
  26. use app\service\id\IdVerify;
  27. use think\App;
  28. use think\Db;
  29. use think\db\Query;
  30. /**
  31. * 靓号管理
  32. */
  33. class MobileController extends UserApi
  34. {
  35. protected $noNeedLogin = "*";
  36. protected $noNeedRight = '*';
  37. /**
  38. * 列表
  39. * @ApiMethod (POST)
  40. * @ApiParams (name="type",description="1靓号,2流量卡,3api号码,默认1")
  41. * @ApiParams (name="search_type",description="fuzzy模糊,precise精准")
  42. * @ApiParams (name="search_last",description="0,1是否搜索尾部")
  43. * @ApiParams (name="city_id",description="地区id")
  44. * @ApiParams (name="keyword",description="搜索内容,模糊就是字符串,精准就是数组")
  45. * @ApiParams (name="sort",description="price_asc价格从低到高,price_desc价格从高到低")
  46. * @ApiParams (name="network",description="网络")
  47. * @ApiParams (name="price_min",description="价格最低数字")
  48. * @ApiParams (name="price_max",description="价格最高数字")
  49. * @ApiParams (name="exclude_num",description="排除数字,数字[1,2,3]")
  50. * @ApiParams (name="num_max",description="数字较多,传数字")
  51. * @ApiParams (name="rule_position",description="规律位置,middle中间,tail尾部")
  52. * @ApiParams (name="rule_name",description="规律名,AAAA什么的")
  53. * @ApiParams (name="limit",description="limit")
  54. * @ApiParams (name="page",description="page")
  55. * @ApiParams (name="is_activity",description="是否是优惠号码")
  56. * @ApiParams (name="chanId",description="分站ID")
  57. * @ApiParams (name="is_offer",description="是[1]否特价号")
  58. * @ApiReturnParams (name=id,description=id)
  59. * @ApiReturnParams (name="type",description="1靓号,2流量卡")
  60. * @ApiReturnParams (name=logo,description=缩略图)
  61. * @ApiReturnParams (name=name,description=号码名称)
  62. * @ApiReturnParams (name=no,description=手机号)
  63. * @ApiReturnParams (name=type,description=1靓号2流量卡)
  64. * @ApiReturnParams (name=network,description=运营商)
  65. * @ApiReturnParams (name=city,description=城市)
  66. * @ApiReturnParams (name=privince,description=省份)
  67. * @ApiReturnParams (name=amount,description=售价)
  68. * @ApiReturnParams (name=amount_original,description=原价)
  69. * @ApiReturnParams (name=amount_exists,description=含话费)
  70. * @ApiReturnParams (name=amount_base,description=售价)
  71. * @ApiReturnParams (name=amount_charge,description=预充)
  72. * @ApiReturnParams (name=summary,description=简介)
  73. * @ApiReturnParams (name=saled,description=是否已出售)
  74. * @ApiReturnParams (name=status,description=0正常1已售2已下架)
  75. * @ApiReturnParams (name=is_activity,description=是否特价号)
  76. * @ApiReturnParams (name=activity_time_end,description=特价过期时间null永不过期)
  77. * @ApiReturnParams (name=view_count,description=正在浏览人数)
  78. * @ApiReturnParams (name=is_private,description=是否民营运营商)
  79. * @ApiReturnParams (name=hits,description="高亮数组,筛选规则才会有,true为高亮",type=array)
  80. * @ApiReturnParams (name=link,description=流量卡跳转链接,有则跳转,没有就跳转详情)
  81. * @ApiReturnParams (name="info.free_app",description=免流APP列表)
  82. * @ApiReturnParams (name="info.describe",description="套餐说明|资费详情")
  83. * @ApiReturnParams (name="info.content",description="详细内容|注意事项")
  84. * @ApiReturnParams (name="info.flow_year",description="每年流量(G)")
  85. * @ApiReturnParams (name="info.fee",description="资费")
  86. * @ApiReturnParams (name="info.first_month_free",description="首月是否免月租")
  87. * @ApiReturnParams (name="info.discount_title",description="简要优惠介绍")
  88. * @ApiReturnParams (name="info.flow_free_limit",description="前多少名免单")
  89. * @ApiReturnParams (name="info.flow_images",description="流量卡详情图片")
  90. */
  91. public function list(){
  92. $data=input();
  93. $page=empty($data['page'])?1:$data['page'];
  94. $limit=input('limit',15);
  95. $chanId=getChanId();
  96. $this->validate($data,[
  97. 'keyword'=>['max:11'],
  98. 'num_max'=>['integer','between:0,9'],
  99. 'rule_position'=>['in:middle,tail'],
  100. ]);
  101. if(empty($data['type'])){
  102. $data['type']=1;
  103. }
  104. if(in_array($data['type'],[Mobile::BEAUTI,Mobile::API])){
  105. $this->listBeauti($data['type']);
  106. }
  107. $hiddenColumn = Mobile::hiddenColumn();
  108. $model=Mobile::show($data);
  109. // $model->field($hiddenColumn,true);
  110. $model->field('mobile.`id`,`status`,`logo`,`name`,`brand`,`no`,`type`,`network`,`city_id`,`city`,`province_id`,`province`,`amount_exists`,`amount_original`,`amount_base`,`amount_charge`,`amount_proxy`,`amount_kill`,`amount`,`top_time`,`rec_time`,`summary`,`is_activity`,`activity_time_end`,`sort`,`sort_line`,`activity_time`,`stock_num`,`is_offer`,`card_status`,`select_num_status`,`product_no`,mobile.`proxy_status`,`send_template`,`not_send_template`,`min_age`,`max_age`,`link`,`sort_proxy`');
  111. $model->where('type',$data['type']);
  112. if(isset($data['price_min']) && is_numeric($data['price_min'])){
  113. $model->where('amount','>=',$data['price_min']);
  114. }
  115. if(!empty($data['price_max']) && is_numeric($data['price_max'])){
  116. $model->where('amount','<=',$data['price_max']);
  117. }
  118. if(!empty($data['search_type']) && !empty($data['keyword'])){
  119. if($data['search_type']=='fuzzy'){
  120. if(isset($data['search_last']) && $data['search_last']==1){
  121. $no=str_pad($data['keyword'],11,'-',STR_PAD_LEFT);
  122. for ($i=0;$i<11;$i++){
  123. if($no[$i]=='-'){
  124. continue;
  125. }
  126. if($i==0){
  127. continue;
  128. }
  129. $pos=$i+1;
  130. $model->where("filter_no_pos_{$pos}",$no[$i]);
  131. }
  132. }else {
  133. $model->where('no', 'like', "%{$data['keyword']}%");
  134. }
  135. }elseif ($data['search_type']=='precise'){
  136. foreach ($data['keyword'] as $k=>$v){
  137. $pos=$k+1;
  138. if($pos==1||$v===""||is_null($v))continue;
  139. $model->where("filter_no_pos_{$pos}",$v);
  140. }
  141. }
  142. }
  143. if(!empty($data['city_id'])){
  144. if (str_contains($data['city_id'],'-all')){
  145. $model->where('province_id',str_replace('-all','',$data['city_id']));
  146. }elseif (is_numeric($data['city_id'])) {
  147. $model->where('city_id', $data['city_id']);
  148. }elseif (preg_match('/\d+-\d+/',$data['city_id'])){
  149. $model->where('city_id',explode('-',$data['city_id']))[1];
  150. }
  151. }
  152. if(!empty($data['network'])){
  153. /*$network=array_column(MobileConstant::getNetwork(),'search','name');
  154. $works=[$data['network']];
  155. foreach ($network as $key=>$networkArr){
  156. if($key==$data['network']){
  157. $works=$networkArr;
  158. break;
  159. }
  160. }
  161. $model->whereIn('network',$works);*/
  162. $model->where('network',$data['network']);
  163. }
  164. if(isset($data['is_activity']) && $data['is_activity']){
  165. $model->where('is_activity',1);
  166. }
  167. if(!empty($data['exclude_num']) && is_array($data['exclude_num'])){
  168. //$model->whereNotLike('no',"%{$data['exclude_num']}%");
  169. foreach ($data['exclude_num'] as $num){
  170. if($num==1){
  171. continue;
  172. }
  173. $model->where("filter_num_{$num}",0);
  174. }
  175. }
  176. if(!empty($data['num_max'])){
  177. $model->where("filter_num_{$data['num_max']}",'>',3);
  178. }
  179. $rules=MobileConstant::getFilters();
  180. if(!empty($data['rule_name'])){
  181. if (!isset($rules[$data['rule_name']])) {
  182. $this->error('规律规则不支持');
  183. }
  184. $rule=$rules[$data['rule_name']];
  185. if(!empty($data['rule_position'])) {
  186. $model->where($rule[$data['rule_position']], 1);
  187. }else{
  188. $model->where(function (Query $query)use ($rule){
  189. $query->where($rule['middle'],1)->whereOr($rule['tail'],1);
  190. });
  191. }
  192. }
  193. if(!empty($data['is_offer'])){
  194. $model->where('is_offer','>',0);
  195. }
  196. /*if($chanId){
  197. $model->whereIn('hold_chan',[0,$chanId]);
  198. }else{
  199. $model->where('hold_chan',0);
  200. }*/
  201. $subIds=[];
  202. if($chanId){
  203. if(empty($data['sort'])) {
  204. $activityData = (clone $model)->where('hold_chan', $chanId)->order('sort_line')->select();
  205. /*$topRecData = (clone $model)
  206. ->join('mobile_sub', "mobile_sub.mobile_id=mobile.id and sub_admin_id=$chanId")
  207. ->where('sub_top_time|sub_rec_time', 1)
  208. ->where(function (Query $query) use ($activityData) {
  209. if ($activityData && $activityData->column('id')) {
  210. $query->whereNotIn('id', $activityData->column('id'));
  211. }
  212. })
  213. ->field('mobile.*')
  214. ->order('sub_sort_line')
  215. ->select();
  216. $subData = $activityData->merge($topRecData);
  217. $subIds = $subData->column('id');*/
  218. $subData=$activityData;
  219. $subIds=$activityData->column('id');
  220. $model->where('is_activity',0);
  221. }
  222. // $model->where('proxy_status', 0)
  223. $model->join('mobile_proxy_status ps', 'mobile.id=ps.mobile_id', 'LEFT')->where(function($q) use($chanId){
  224. $q->where('mobile.proxy_id', $chanId)->where('ps.proxy_id', $chanId)->whereOr(function($q) use($chanId){
  225. $q->where('status', 0)->where('mobile.proxy_id is null')->where('ps.proxy_status', 0)->where('ps.proxy_id', $chanId);
  226. });
  227. });
  228. }else{
  229. $model->where('hold_chan',0)->where('proxy_id is null');
  230. }
  231. if($subIds){
  232. $model->whereNotIn('mobile.id',$subIds);
  233. }
  234. if(!empty($data['sort'])){
  235. if($data['sort']=='price_asc'){
  236. $model->order('amount','asc');
  237. }elseif($data['sort']=='price_desc'){
  238. $model->order('amount','desc');
  239. }
  240. }else{
  241. if($data['type']==1) {
  242. $model->order('sort_line');
  243. }
  244. elseif($chanId){
  245. $model->order('sort_proxy asc, sort asc');
  246. }
  247. else{
  248. $model->order('sort');
  249. }
  250. }
  251. // dump($model->fetchSql()->select());exit;
  252. $list=$model->paginate($limit,true)->toArray();
  253. $listData=$list['data'];
  254. if($page==1 && isset($subData)){
  255. foreach (array_reverse($subData->toArray()) as $item){
  256. array_unshift($listData,$item);
  257. }
  258. }
  259. $list['data']=$listData;
  260. $this->success('',$list);
  261. }
  262. protected function listBeauti($type){
  263. $chanId=getChanId();
  264. $data=input();
  265. $page=empty($data['page'])?1:$data['page'];
  266. $limit=input('limit')?:15;
  267. $query=[
  268. 'query'=>[
  269. "bool"=>[
  270. 'should'=>[
  271. [
  272. 'bool'=>[
  273. 'must'=>[
  274. [
  275. 'terms'=>[
  276. 'status'=>Mobile::beautiFrontShowStatus(),
  277. ],
  278. ],
  279. [
  280. 'bool'=>[
  281. 'must'=>[
  282. [
  283. 'term'=>[
  284. 'is_activity'=>0,
  285. ],
  286. ],
  287. [
  288. 'term'=>[
  289. 'hold_chan'=>0,
  290. ]
  291. ]
  292. ]
  293. ]
  294. ],
  295. [
  296. 'term'=>[
  297. 'type'=>$type,
  298. ]
  299. ]
  300. ]
  301. ]
  302. ],
  303. [
  304. 'bool'=>[
  305. 'must'=>[
  306. [
  307. 'terms'=>[
  308. 'status'=>Mobile::beautiFrontShowStatus(),
  309. ],
  310. ],
  311. [
  312. 'bool'=>[
  313. 'must'=>[
  314. [
  315. 'term'=>[
  316. 'is_activity'=>1,
  317. ],
  318. ],
  319. [
  320. 'term'=>[
  321. 'hold_chan'=>$chanId,
  322. ]
  323. ]
  324. ]
  325. ]
  326. ],
  327. [
  328. 'term'=>[
  329. 'type'=>$type,
  330. ]
  331. ]
  332. ]
  333. ]
  334. ]
  335. ]
  336. ]
  337. ],
  338. 'size'=>$limit,
  339. 'from'=>($page-1)*$limit,
  340. ];
  341. if(isset($data['price_min']) && is_numeric($data['price_min'])){
  342. $query['query']['bool']['should'][0]['bool']['must'][]['range']['amount']['gte']=(int)$data['price_min'];
  343. $query['query']['bool']['should'][1]['bool']['must'][]['range']['amount']['gte']=(int)$data['price_min'];
  344. }
  345. if(!empty($data['price_max']) && is_numeric($data['price_max'])){
  346. $query['query']['bool']['should'][0]['bool']['must'][]['range']['amount']['lte']=(int)$data['price_max'];
  347. $query['query']['bool']['should'][1]['bool']['must'][]['range']['amount']['lte']=(int)$data['price_max'];
  348. }
  349. if(!empty($data['sort'])){
  350. if($data['sort']=='price_asc'){
  351. $query['sort']['amount']['order']='asc';
  352. }elseif($data['sort']=='price_desc'){
  353. $query['sort']['amount']['order']='desc';
  354. }
  355. }elseif(isset($data['num_max']) && is_numeric($data['num_max'])){
  356. $query['sort']["filter_num_{$data['num_max']}"]['order']='desc';
  357. }else{
  358. /*$query['sort']['activity_time']['order'] = 'desc';
  359. $query['sort']['rec_time']['order'] = 'desc';
  360. $query['sort']['top_time']['order'] = 'desc';
  361. $query['sort']['sort']['order'] = 'asc';*/
  362. $query['sort']['sort_line']['order'] = 'asc';
  363. }
  364. if(!empty($data['search_type']) && !empty($data['keyword'])){
  365. if($data['search_type']=='fuzzy'){
  366. if(isset($data['search_last']) && $data['search_last']==1){
  367. $query['query']['bool']['should'][0]['bool']['must'][]['wildcard']['no']=['value'=>"*{$data['keyword']}"];
  368. $query['query']['bool']['should'][1]['bool']['must'][]['wildcard']['no']=['value'=>"*{$data['keyword']}"];
  369. }else {
  370. $query['query']['bool']['should'][0]['bool']['must'][]['wildcard']['no']=['value'=>"*{$data['keyword']}*"];
  371. $query['query']['bool']['should'][1]['bool']['must'][]['wildcard']['no']=['value'=>"*{$data['keyword']}*"];
  372. }
  373. }elseif ($data['search_type']=='precise'){
  374. foreach ($data['keyword'] as $k=>$v){
  375. $pos=$k+1;
  376. if($pos==1||!is_numeric($v))continue;
  377. $query['query']['bool']['should'][0]['bool']['must'][]['term']["filter_no_pos_{$pos}"]=$v;
  378. $query['query']['bool']['should'][1]['bool']['must'][]['term']["filter_no_pos_{$pos}"]=$v;
  379. }
  380. }
  381. }
  382. if(!empty($data['is_offer'])){
  383. $query['query']['bool']['should'][0]['bool']['must'][]['range']["is_offer"]['gt']=0;
  384. $query['query']['bool']['should'][1]['bool']['must'][]['range']["is_offer"]['gt']=0;
  385. }
  386. if(!empty($data['city_id'])){
  387. if (str_contains($data['city_id'],'-all')){
  388. $provinceId=str_replace('-all','',$data['city_id']);
  389. $query['query']['bool']['should'][0]['bool']['must'][]['term']["province_id"]=$provinceId;
  390. $query['query']['bool']['should'][1]['bool']['must'][]['term']["province_id"]=$provinceId;
  391. }elseif (is_numeric($data['city_id'])) {
  392. $query['query']['bool']['should'][0]['bool']['must'][]['term']["city_id"]=$data['city_id'];
  393. $query['query']['bool']['should'][1]['bool']['must'][]['term']["city_id"]=$data['city_id'];
  394. }elseif (preg_match('/\d+-\d+/',$data['city_id'])){
  395. $cityId=explode('-',$data['city_id'])[1];
  396. $query['query']['bool']['should'][0]['bool']['must'][]['term']["city_id"]=$cityId;
  397. $query['query']['bool']['should'][1]['bool']['must'][]['term']["city_id"]=$cityId;
  398. }
  399. }
  400. $rules=MobileConstant::getFilters();
  401. if(!empty($data['rule_name'])){
  402. if (!isset($rules[$data['rule_name']])) {
  403. $this->error('规律规则不支持');
  404. }
  405. $rule=$rules[$data['rule_name']];
  406. if(!empty($data['rule_position'])) {
  407. $query['query']['bool']['should'][0]['bool']['must'][]['term'][$rule[$data['rule_position']]]=1;
  408. $query['query']['bool']['should'][1]['bool']['must'][]['term'][$rule[$data['rule_position']]]=1;
  409. }else{
  410. $ruleQuery=[
  411. 'bool'=>[
  412. 'should'=>[
  413. [
  414. 'term'=>[
  415. $rule['middle']=>1,
  416. ]
  417. ],
  418. [
  419. 'term'=>[
  420. $rule['tail']=>1,
  421. ]
  422. ]
  423. ]
  424. ]
  425. ];
  426. $query['query']['bool']['should'][0]['bool']['must'][]=$ruleQuery;
  427. $query['query']['bool']['should'][1]['bool']['must'][]=$ruleQuery;
  428. }
  429. }
  430. if(!empty($data['network'])){
  431. $query['query']['bool']['should'][0]['bool']['must'][]['term']['network']=$data['network'];
  432. $query['query']['bool']['should'][1]['bool']['must'][]['term']['network']=$data['network'];
  433. }
  434. if(!empty($data['exclude_num']) && is_array($data['exclude_num'])){
  435. $data['exclude_num']=array_unique($data['exclude_num']);
  436. foreach ($data['exclude_num'] as $num){
  437. if(!is_numeric($num)){
  438. continue;
  439. }
  440. $query['query']['bool']['should'][0]['bool']['must'][]['term']["filter_num_{$num}"]=0;
  441. $query['query']['bool']['should'][1]['bool']['must'][]['term']["filter_num_{$num}"]=0;
  442. }
  443. }
  444. if(isset($data['is_activity']) && $data['is_activity']){
  445. $query['query']['bool']['should'][0]['bool']['must'][]['term']['is_activity']=1;
  446. $query['query']['bool']['should'][1]['bool']['must'][]['term']['is_activity']=1;
  447. }else{
  448. $activityShow=config('site.activity_no_show')?:1;
  449. if($activityShow==2){
  450. $query['query']['bool']['should'][0]['bool']['must'][]['term']['is_activity']=0;
  451. $query['query']['bool']['should'][1]['bool']['must'][]['term']['is_activity']=0;
  452. }
  453. }
  454. $esData = EsMobileService::get($query);
  455. $esData['current_page']=$page;
  456. $esData['per_page']=$limit;
  457. $esData['has_more']=count($esData['data'])>=$limit;
  458. $rulePosition=$data['rule_position']??'';
  459. if(!empty($data['rule_name'])){
  460. foreach ($esData['data'] as &$mobile){
  461. $computer=MobileComputer::setMobile($mobile['no']);
  462. if($rulePosition=='tail'){
  463. App::invokeMethod([$computer,'check_'.$rule['tail']]);
  464. $hitTail=$computer->getHits();
  465. $mobile['hits']=MobileComputer::makeHits($mobile['no'],[$hitTail]);
  466. }elseif ($rulePosition=='middle'){
  467. App::invokeMethod([$computer,'check_'.$rule['middle']]);
  468. $hitMiddle=$computer->getHits();
  469. if($hitMiddle){
  470. $mobile['hits']=MobileComputer::makeHits($mobile['no'],[$hitMiddle]);
  471. }
  472. }else{
  473. $mobile['hits']=[];
  474. }
  475. }
  476. }
  477. $this->success('',$esData);
  478. }
  479. /**
  480. * 号码详情
  481. * @ApiParams (name=id,description=号码id)
  482. * @ApiReturnParams (name=copy_word,description=复制的内容)
  483. * @ApiReturnParams (name=card_status,description=1需上传三张身份证照片)
  484. */
  485. public function show(){
  486. $data=$this->_validate([
  487. 'id'=>['require']
  488. ]);
  489. $user=$this->auth->getUser();
  490. $mobile=Mobile::where('id','id')->with(['info'])->find($data['id']);
  491. if(!$mobile){
  492. EsMobileService::delMobiles([$data['id']]);
  493. $this->error('您查找的手机号已下架或不存在');
  494. }
  495. if($mobile['type']==1) {
  496. EsMobileService::addMobile($mobile);
  497. }
  498. //MobileUserHistory::add($user,$mobile);
  499. $mobile->addViewCount();
  500. $mobile->append(['view_count','copy_word']);
  501. $mobile->makeHidden();
  502. MobileInfo::makeFreeApp($mobile['info']);
  503. $this->success('',$mobile);
  504. }
  505. /**
  506. * 下单
  507. * @ApiMethod (POST)
  508. * @ApiParams (name=mobile_id,description=手机号ID)
  509. * @ApiParams (name=name,description=姓名)
  510. * @ApiParams (name=phone,description=手机号)
  511. * @ApiParams (name=sms_code,description=验证码)
  512. * @ApiParams (name=id_no,description="身份号码,450804198608275870",sample="450804198608275870")
  513. * @ApiParams (name=open_idcard_face_img,description="身份证正面照片",required=false)
  514. * @ApiParams (name=open_idcard_back_img,description="身份证反面照片",required=false)
  515. * @ApiParams (name=open_face_img,description="脸部照片",required=false)
  516. * @ApiParams (name=county,description="城市ID,区县id")
  517. * @ApiParams (name=address,description=详细地址)
  518. * @ApiParams (name=remark,description=备注)
  519. * @ApiParams (name=no,description=选号)
  520. * @ApiParams (name=pay_type,description="1微信2支付宝3京东4抖音小程序5快手小程序")
  521. * @ApiParams (name=return_url,description="支付完成回调页面链接")
  522. * @ApiParams (name=clickid,description="巨量引擎clickid")
  523. * @ApiReturnParams (name=pay_url,description="支付链接")
  524. * @ApiReturnParams (name=without_pay,description="是否不需要支付")
  525. * @ApiReturnParams (name=res,description="抖音支付时返回参数")
  526. */
  527. public function apply(){
  528. $needId=config('site.system_id_form_open')?true:false;
  529. $user=$this->auth->getUser();
  530. $data=$this->_validate([
  531. 'mobile_id'=>'require',
  532. 'name|姓名'=>['require','max:20'],
  533. 'phone|手机号'=>'require|mobile',
  534. //'id_no|身份证'=>['require','regex'=>'/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/'],
  535. 'county|地区'=>'require|integer',
  536. 'address|详细地址'=>['require','min:4', 'max:100'],
  537. ]);
  538. if($needId){
  539. $this->_validate([
  540. 'id_no|身份证'=>['require','regex'=>'/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/'],
  541. ]);
  542. }
  543. Db::startTrans();
  544. $mobile=Mobile::lock(true)->findOrFail($data['mobile_id']);
  545. if($mobile['type']==1){
  546. $this->_validate([
  547. 'pay_type'=>'require|in:'.implode(',',array_keys(MobileOrder::$payTypes)),
  548. ]);
  549. }
  550. if($mobile['type'] == 2){
  551. $this->_validate([
  552. 'id_no|身份证'=>['require','regex'=>'/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/'],
  553. ]);
  554. if($mobile['card_status']){
  555. $this->_validate([
  556. 'open_idcard_face_img|身份证正面照片' => 'require',
  557. 'open_idcard_back_img|身份证反面照片' => 'require',
  558. 'open_face_img|脸部照片' => 'require',
  559. ]);
  560. }
  561. $blackListConfig = config('site.flow_blacklist');
  562. if($blackListConfig){
  563. $blackList = [];
  564. $blackListTmp = explode("\r\n", $blackListConfig);
  565. foreach($blackListTmp as $key=>$val){
  566. $tmpId = explode(' ', $val);
  567. if(isset($tmpId[1]) && $tmpId[1]) $blackList[] = $tmpId[1];
  568. }
  569. if(in_array($data['id_no'], $blackList)) $this->error('该身份证号已被禁用');
  570. }
  571. $flowLimitAgeStart = $mobile['min_age'];
  572. $flowLimitAgeEnd = $mobile['max_age'];
  573. $birthDay = IdVerify::instance()->getBirthDay($data['id_no']);
  574. $age = $this->countAge($birthDay);
  575. if($flowLimitAgeStart && $age < $flowLimitAgeStart) $this->error('该身份证号年龄被限制');
  576. if($flowLimitAgeEnd && $age > $flowLimitAgeEnd) $this->error('该身份证号年龄被限制');
  577. if($mobile['send_template']){
  578. if(!Mobile::sendTemplateLimit($mobile, $data['county'])) $this->error('该地区暂不支持订购');
  579. }
  580. if($mobile['not_send_template']){
  581. if(Mobile::notSendTemplateLimit($mobile, $data['county'])) $this->error('该地区暂不支持订购');
  582. }
  583. }
  584. $mobile->shouldBuy();
  585. Area::shouldSend($data['county']);
  586. $system_sms_open = config('site.system_sms_open') ? true : false;
  587. if($system_sms_open && $mobile->needCheckSmsCode()) {
  588. SmsSend::setMobile($data['phone'])->setCode($data['sms_code'] ?? '')->setEvent('order')->check();
  589. }
  590. #禁止重复下单
  591. $hasOrder=MobileOrder::where('mobile_id',$mobile->id)
  592. ->where('phone',$data['phone'])
  593. ->where('create_time','>',time()-10)
  594. ->value('id');
  595. if($hasOrder){
  596. Db::rollback();
  597. $this->error('操作频繁');
  598. }
  599. // if($needId && Mobile::isType($mobile['type'])){
  600. if(Mobile::isType($mobile['type'])){
  601. // if($needId && !App::$debug) {
  602. if($needId || $mobile['type'] == 2) {
  603. IdVerify::instance()->check($data['name'] ?? '', $data['id_no'] ?? '');
  604. }
  605. if($mobile['type'] == 2){
  606. $orderLimit = config('site.'.$mobile['brand']);
  607. if($orderLimit && MobileOrder::orderLimit($data['id_no'], $orderLimit, $mobile['brand'])) $this->error('订购频繁');
  608. }
  609. //elseif(MobileOrder::hasOrdered($data['phone'],$mobile)){
  610. elseif(MobileOrder::hasOrdered($data['phone'],$mobile['brand'])){
  611. $this->error('订购频繁');
  612. }
  613. }
  614. $order = $data;
  615. $order['s_id']=getChanId();
  616. $order['admin_id'] = $mobile['proxy_id'];
  617. $order['no'] = array_key_exists('no',$data)?$data['no']:$mobile['no'];
  618. $order['city'] = implode(',', Area::getTreeId($data['county']));
  619. $order['amount_original'] = $mobile['amount_original'];
  620. $order['amount_hd'] = $mobile['amount'];
  621. $order['amount_charge'] = $mobile['amount_charge'];
  622. $order['amount'] = $mobile['amount'];
  623. $order['amount_di'] = $mobile['amount_di'];
  624. $order['amount_base'] = bcsub($mobile['amount'],$mobile['amount_charge']);
  625. $order['type'] = $mobile['type'];
  626. $order['status'] = 0;
  627. if($user){
  628. $order['user_id']=$user['id'];
  629. }
  630. unset($order['county'], $order['sms_code']);
  631. $mobileOrder = (new MobileOrder);
  632. if($mobile['type']==2){
  633. $mobileOrder->flowOrderSubmit();
  634. }
  635. $mobileOrder->allowField(true)->save($order);
  636. //$succ=$mobileOrder;
  637. //if($mobile['type']==1) {
  638. $succ = $this->pay($mobileOrder, $data);
  639. //}
  640. #下架号码
  641. /*$mobile['status']=$mobile::S_DOWN;
  642. $mobile->save();*/
  643. Db::commit();
  644. $this->success('', $succ);
  645. }
  646. protected function pay(MobileOrder $mobileOrder,$data,$is_continue=false){
  647. $params = input('param.');
  648. $clickid = $params['clickid'] ?? '';
  649. $data['return_url']=h5_link('pages/PaySuccess/PaySuccess?id='.$mobileOrder['id']);
  650. // if($mobileOrder['type']==2){
  651. // OceanEngineService::setQuery(['clickid'=>input('clickid')])->setAddon(['order_no'=>input('clickid')])->form();
  652. // }
  653. $succ=[
  654. 'pay_url'=>'',
  655. 'id'=>$mobileOrder['id'],
  656. 'without_pay'=>0,
  657. 'res'=>null,
  658. ];
  659. if($mobileOrder['amount']==0){
  660. $succ['without_pay']=1;
  661. $mobileOrder->paySuccessCallback();
  662. try {
  663. OceanEngineService::setQuery(['clickid'=>$clickid])->setAddon(['order_no'=>$clickid])->shopping();
  664. GantanhaoService::orderPurchase($mobileOrder);
  665. }catch (\Exception $e){}
  666. return $succ;
  667. }
  668. $payment=Payment::create([
  669. 'order_no'=>session_create_id(),
  670. 'amount'=>$mobileOrder['amount'],
  671. 'mobile_order_id'=>$mobileOrder['id'],
  672. 'params'=>[
  673. 'clickid'=>$clickid,
  674. ]
  675. ]);
  676. $filename=session_create_id(date('Ymd'));
  677. if(!is_dir($dir=RUNTIME_PATH.'/payment/')) {
  678. @mkdir($dir, 0777, true);
  679. }
  680. if($data['pay_type']==1){
  681. $info=Service::submitOrder($payment['amount'],
  682. $payment['order_no'],'wechat',"购买手机号{$mobileOrder['no']}",
  683. Service::notifyUrl('wechat',$payment['order_no']),$data['return_url']??'','wap');
  684. file_put_contents(RUNTIME_PATH.'/payment/'.$filename,$info->getContent());
  685. $succ['pay_url']=url('/index/index/payment/a/'.$filename,[],true,true);
  686. }elseif ($data['pay_type']==2){
  687. $info=Service::submitOrder($payment['amount'],
  688. $payment['order_no'],'alipay',"购买手机号{$mobileOrder['no']}",
  689. Service::notifyUrl('alipay',$payment['order_no']),$data['return_url']??'','wap');
  690. file_put_contents(RUNTIME_PATH.'/payment/'.$filename,view('alipay',['form'=>$info->getContent()])->getContent());
  691. $succ['pay_url']=url('/index/index/payment/a/'.$filename,[],true,true);
  692. }elseif ($data['pay_type']==3){
  693. $jdpay=App::invokeClass(Jdpay::class);
  694. $payData=$jdpay->order($payment['order_no'],$payment['amount'],"购买手机号{$mobileOrder['no']}");
  695. $succ=array_merge($succ,$payData);
  696. }elseif ($data['pay_type']==4){
  697. $payData=ByteDancePay::setInfo($payment['order_no'],$payment['amount'],"购买手机号{$mobileOrder['no']}")->get();
  698. $succ['res']=$payData;
  699. if(!$is_continue) {
  700. $push = new ByteDanceOrderPush();
  701. $push->setOrder($mobileOrder);
  702. $push->setPayment($payment);
  703. $push->get();
  704. }
  705. }elseif ($data['pay_type']==5){
  706. $getData['access_token'] = $this->_getKsAccessToken();
  707. $getData['app_id'] = config('kuaishou.appid');
  708. $user=$this->auth->getUser();
  709. $postData['open_id'] = Db('user')->where(['id'=>$user['id']])->value('k_openid'); //用户的openid
  710. $postData['out_order_no'] = $payment['order_no'];
  711. // $postData['total_amount'] = $payment['amount'];
  712. $postData['total_amount'] = $payment['amount']*100;
  713. $postData['subject'] = "购买手机号{$mobileOrder['no']}";
  714. $postData['detail'] = "购买手机号{$mobileOrder['no']}";
  715. // $postData['attach'] = 'asdfasdf';
  716. $postData['type'] = 1856;
  717. $postData['expire_time'] = 172800;
  718. $postData['notify_url'] =request()->domain()."/index/payment/notify_ks/order_no/{$payment['order_no']}";
  719. $sign = _makeKsSgin($getData, $postData);
  720. $postData['sign'] = $sign;
  721. $url = 'https://open.kuaishou.com/openapi/mp/developer/epay/create_order?' . http_build_query($getData);
  722. $json = json_encode($postData, 320);
  723. $res = jsonPost($url, $json);
  724. $resArr=json_decode($res,true);
  725. if(!is_array($resArr)){
  726. $this->error('请求支付失败');
  727. }
  728. if($resArr['result']!=1){
  729. $this->error($resArr['error_msg'],$postData);
  730. }
  731. $succ['res']=$resArr['order_info'];
  732. }
  733. return $succ;
  734. }
  735. private function _getKsAccessToken() {
  736. return AccessToken::get();
  737. }
  738. /**
  739. * 继续支付
  740. * @ApiParams (name=id,description=订单id)
  741. * @ApiParams (name=pay_type,description=支付方式与下单一样)
  742. * @ApiParams (name=return_url,description="支付完成回调页面链接")
  743. */
  744. public function continue_pay(){
  745. $data=$this->_validate([
  746. 'id'=>['require'],
  747. 'pay_type'=>'require|in:'.implode(',',array_keys(MobileOrder::$payTypes)),
  748. ]);
  749. $mobileOrder=MobileOrder::whereNull('pay_time')->findOrFail($data['id']);
  750. $mobileOrder->continuePay();
  751. $succ=$this->pay($mobileOrder,$data,true);
  752. $this->success('',$succ);
  753. }
  754. /**
  755. * 订单详情
  756. * @ApiParams (name=id,description=订单id)
  757. * @ApiReturnParams (name=no,description=手机号)
  758. * @ApiReturnParams (name=order_no,description=订单号)
  759. * @ApiReturnParams (name=amount_hd,description=活动价)
  760. * @ApiReturnParams (name=amount_original,description=原价)
  761. * @ApiReturnParams (name=amount_charge,description=预充)
  762. * @ApiReturnParams (name=describe,description=套餐说明)
  763. * @ApiReturnParams (name=proxy.wx_qr,description=客服二维码)
  764. * @ApiReturnParams (name=name,description=收货人)
  765. * @ApiReturnParams (name=phone,description=收货人手机号)
  766. * @ApiReturnParams (name=id_no,description=收货人身份证)
  767. * @ApiReturnParams (name=address,description=收货地址)
  768. * @ApiReturnParams (name=remark,description=备注)
  769. * @ApiReturnParams (name=create_time,description=下单时间)
  770. * @ApiReturnParams (name=amount,description=订单金额)
  771. * @ApiReturnParams (name=trans_name,description=快递名称)
  772. * @ApiReturnParams (name=trans_no,description=快递单号)
  773. * @ApiReturnParams (name=status,description="0=>'待付款',10=>'已付款',15=>'待发货',17=>'有号码未发货',20=>'待开卡',25=>'已完成',30=>'申请退款',50=>'已关闭',60=>'无号码',70=>'换卡',80=>'争议单',90=>'已退款',100=>'退款驳回',110=>'审核失败'")
  774. * @ApiReturnParams (name=reason,description="状态为110审核失败时,敢探号审核失败原因")
  775. * @ApiReturnParams (name=open_uploaded,description=是否已上传开卡资料)
  776. * @ApiReturnParams (name=open_idcard_face_img,description=身份证正面照)
  777. * @ApiReturnParams (name=open_idcard_back_img,description=身份证反面照)
  778. * @ApiReturnParams (name=open_face_img,description=头像照)
  779. * @ApiReturnParams (name=open_name,description=姓名)
  780. * @ApiReturnParams (name=open_id_no,description=身份证号码)
  781. * @ApiReturnParams (name=open_phone,description=手机号)
  782. * @ApiReturnParams (name=pay_time,description=支付时间)
  783. * @ApiReturnParams (name=expire_time,description=过期时间)
  784. */
  785. public function order_detail(){
  786. $order = MobileOrder::with(['proxy','info'])->findOrFail(input('id'));
  787. $order['proxy'] && $order['proxy']->hidden(['password']);
  788. $order['describe'] = $order['info']['info']['describe']??'';
  789. $reason = $order['gantanhao_data_notify'] ? json_decode($order['gantanhao_data_notify'], true) : '';
  790. $order['reason'] = $reason ? $reason['reason'] : '';
  791. $this->success('',$order);
  792. }
  793. /**
  794. * 订单列表
  795. * @ApiParams (name=page,description=page)
  796. * @ApiParams (name=limit,description=limit)
  797. * @ApiParams (name=phone,description="手机号,小程序可不传")
  798. * @ApiParams (name=type,description=1靓号2流量卡)
  799. * @ApiParams (name=status,description="状态:0待付款10:已付款15:待发货17:有号码未发货20:待开卡25:已完成30:申请退款50:已关闭60:无号码70:换卡80:争议单90:已退款100:退款驳回110:审核失败")
  800. * @ApiSummary (流量卡状态15:已提运营25:已完成)
  801. */
  802. public function order_list(){
  803. $user=$this->auth->getUser();
  804. $data=input();
  805. $this->_validate([
  806. 'type|类型'=>['in:1,2'],
  807. ]);
  808. if(!$user){
  809. $this->_validate([
  810. 'phone|手机号'=>['require'],
  811. ]);
  812. }
  813. $type=$data['type']??1;
  814. $type=$type?:1;
  815. $order=MobileOrder::with(['proxy','info'])
  816. ->where(function ($q)use ($user,$data){
  817. if(!empty($data['phone'])){
  818. $q->where('phone',$data['phone']);
  819. }elseif ($user){
  820. $q->where('user_id',$user['id']);
  821. }else{
  822. $q->where('id',1);
  823. }
  824. })
  825. ->filterShow($type)
  826. ->where('type',$type)
  827. ->order('id','desc');
  828. if(isset($data['status']) && $data['status']!==''){
  829. if($data['status']==0){
  830. $status=[
  831. $data['status'],17,60,70,80,
  832. ];
  833. $order->whereIn('status',$status);
  834. }else {
  835. $order->where('status', $data['status']);
  836. }
  837. }
  838. $ret=$order->paginate(input('limit',15));
  839. $this->success('',$ret);
  840. }
  841. /**
  842. * 筛选配置
  843. *
  844. */
  845. public function config(){
  846. $config=[];
  847. $networks=MobileConstant::getNetworkString();
  848. $config['network']=$networks;
  849. $config['rule']=MobileConstant::getRuleKeys();
  850. $this->success('',$config);
  851. }
  852. /**
  853. * 上传开卡资料
  854. * @ApiParams (name=id,description=订单id)
  855. * @ApiParams (name=idcard_face_img,description=身份证正面照片)
  856. * @ApiParams (name=idcard_back_img,description=身份证反面照片)
  857. * @ApiParams (name=face_img,description=本人照片)
  858. * @ApiParams (name=name,description=本人姓名)
  859. * @ApiParams (name=id_no,description=本人身份证号码)
  860. * @ApiParams (name=phone,description=本人联系电话)
  861. */
  862. public function upload_identity(){
  863. $data=$this->_validate([
  864. 'id'=>['require'],
  865. 'idcard_face_img|身份证正面照片'=>['require','url'],
  866. 'idcard_back_img|身份证反面照片'=>['require','url'],
  867. 'face_img|本人照片'=>['require','url'],
  868. 'name|本人姓名'=>['require','max:10'],
  869. 'id_no|本人身份证号码'=>['require'],
  870. 'phone|本人联系电话'=>['require','integer'],
  871. ]);
  872. $order=MobileOrder::findOrFail($data['id']);
  873. if($order['open_uploaded']){
  874. $this->error('请勿再次上传');
  875. }
  876. IdVerify::instance()->check($data['name'],$data['id_no']);
  877. $order['open_uploaded']=1;
  878. $order['open_idcard_face_img']=$data['idcard_face_img'];
  879. $order['open_idcard_back_img']=$data['idcard_back_img'];
  880. $order['open_face_img']=$data['face_img'];
  881. $order['open_name']=$data['name'];
  882. $order['open_id_no']=$data['id_no'];
  883. $order['open_phone']=$data['phone'];
  884. if(!$order->save()){
  885. $this->error('保存失败');
  886. }
  887. $this->success('');
  888. }
  889. /**
  890. * 预定号码
  891. * @ApiParams (name=no,description=号码)
  892. * @ApiParams (name=price_min,description=最低承受价格)
  893. * @ApiParams (name=price_max,description=最高承受价格)
  894. * @ApiParams (name=remark,description=备注)
  895. * @ApiParams (name=name,description=姓名)
  896. * @ApiParams (name=phone,description=联系电话)
  897. * @ApiParams (name=county,description=区县ID)
  898. * @ApiParams (name=address,description=详细地址)
  899. */
  900. public function order_no(){
  901. $data=$this->_validate([
  902. 'no|预定号码'=>['require','integer','min:3','max:8'],
  903. //'price_min'=>['require','integer','min:0'],
  904. 'price_max|可承受价格'=>['require','integer','min:0'],
  905. 'name|姓名'=>['require'],
  906. 'phone|联系电话'=>['require','integer','length:11'],
  907. 'county|城市'=>['require','integer'],
  908. 'address|详细地址'=>['require','length:0,250'],
  909. ]);
  910. $no=new MobileOrderNo;
  911. $data['city']=implode(',',Area::getTreeId($data['county']));
  912. $no->allowField(true)->save($data);
  913. $this->success('');
  914. }
  915. /**
  916. * 横幅播报
  917. * @ApiReturnParams (name=ordered_num,description=已订购人数)
  918. * @ApiReturnParams (name=no,description=号码)
  919. * @ApiReturnParams (name=name,description=人名)
  920. * @ApiReturnParams (name=num,description=人数)
  921. */
  922. public function ordered_show(){
  923. $data=[];
  924. $data['ordered_num']=SysConfig::look('mo_ordered_num',0);
  925. $data['ordered_list']=AdIndexOrderedFlow::field('name,no,num')
  926. ->order('num','asc')
  927. ->select();
  928. foreach ($data['ordered_list'] as $item){
  929. $item['no']=substr($item['no'],0,3).'****'.substr($item['no'],7,4);
  930. $item['name']=mb_substr($item['name'],0,mb_strlen($item['name'])-1).'*';
  931. }
  932. $this->success('',$data);
  933. }
  934. /**
  935. * 退款
  936. * @ApiMethod (POST)
  937. * @ApiParams (name=id,description=订单id)
  938. * @ApiParams (name=reason,description=退款原因)
  939. */
  940. public function refund(){
  941. $data=$this->_validate([
  942. 'id'=>'require',
  943. 'reason'=>'require|max:250',
  944. ]);
  945. Db::startTrans();
  946. $order=MobileOrder::lock(true)->findOrFail($data['id']);
  947. $order->checkAllowRefund();
  948. $order->makeUserRefund($data['reason']);
  949. Db::commit();
  950. $this->success();
  951. }
  952. /**
  953. * 查询物流
  954. * @ApiMethod (POST)
  955. * @ApiParams (name=id,description=订单id)
  956. * @ApiReturnParams (name=AcceptTime,description=时间)
  957. * @ApiReturnParams (name=AcceptStation,description=描述)
  958. */
  959. public function logistics(){
  960. $data=$this->_validate([
  961. 'id'=>['require'],
  962. ]);
  963. $order=MobileOrder::findOrFail($data['id']);
  964. $logistics=[];
  965. if(!$order['trans_id']||!$order['trans_no']){
  966. $this->success('',$logistics);
  967. }
  968. $logistics=TransferCheck::instance()->setNo($order['trans_no'])->setLogisticsCompany(LogisticsCompany::get($order['trans_id']))->setPhone($order['phone'])->setName($order['name'])->get();
  969. $this->success('',$logistics);
  970. }
  971. /**
  972. * 预占号码
  973. * @ApiParams (name=id,description=号码ID)
  974. * @ApiParams (name=chanId,description=通道ID)
  975. */
  976. public function take(){
  977. $data=$this->_validate([
  978. 'id|号码'=>['require','gt:0'],
  979. ]);
  980. $open=config('site.auto_take_open');
  981. $discount=config('site.auto_take_discount');
  982. if(!$open){
  983. $this->success('未开启');
  984. }
  985. if($discount<=0||$discount>10){
  986. $this->success('参数错误');
  987. }
  988. Db::startTrans();
  989. $mobile=Mobile::lock(true)->findOrFail($data['id']);
  990. if($mobile['is_activity']){
  991. Db::rollback();
  992. $this->success('已开启');
  993. }
  994. $chanId=getChanId();
  995. $amount_kill=bcmul($mobile['amount_base'],$discount/10,0);
  996. $mobile->makeActivity($amount_kill,$chanId);
  997. Db::commit();
  998. $this->success('改价成功');
  999. }
  1000. /**
  1001. * 流量卡上传身份证照片
  1002. * @ApiMethod (POST)
  1003. * @ApiParams (name=id,description=订单id)
  1004. * @ApiParams (name=idcard_face_img,description=身份证正面照片)
  1005. * @ApiParams (name=idcard_back_img,description=身份证反面照片)
  1006. * @ApiParams (name=face_img,description=本人照片)
  1007. */
  1008. public function upload_identity_flow(){
  1009. $data = $this->_validate([
  1010. 'id'=>['require'],
  1011. 'idcard_face_img|身份证正面照片'=>['require','url'],
  1012. 'idcard_back_img|身份证反面照片'=>['require','url'],
  1013. 'face_img|本人照片'=>['require','url']
  1014. ]);
  1015. $order = MobileOrder::findOrFail($data['id']);
  1016. $dataGantanhao = $order['gantanhao_data'] ? json_decode($order['gantanhao_data'], true) : [];
  1017. if(!$dataGantanhao || !isset($dataGantanhao['str_rand']) || !$dataGantanhao['str_rand']){
  1018. $this->error('暂无法重新上传');
  1019. }
  1020. try{
  1021. GantanhaoService::orderPhotos($dataGantanhao['str_rand'], $data);
  1022. $order['open_idcard_face_img'] = $data['idcard_face_img'];
  1023. $order['open_idcard_back_img'] = $data['idcard_back_img'];
  1024. $order['open_face_img'] = $data['face_img'];
  1025. $order->save();
  1026. }
  1027. catch(\Exception $e){
  1028. if(stripos($e,'413')){
  1029. $this->error('图片过大');
  1030. }
  1031. Log::error("流量卡上传身份证照片:".json_encode($e));
  1032. $this->error('保存失败');
  1033. }
  1034. $this->success('上传成功');
  1035. }
  1036. /**
  1037. * 计算年龄
  1038. */
  1039. private function countAge($birthDay = ''){
  1040. if(!$birthDay) return false;
  1041. $age = strtotime($birthDay['year'].$birthDay['month'].$birthDay['day']);
  1042. if($age === false) return false;
  1043. list($y, $m, $d) = explode('-', date('Y-m-d'));
  1044. $age = $y - $birthDay['year'];
  1045. if((int)($m.$d) < (int)($birthDay['month'].$birthDay['day'])) $age -= 1;
  1046. return $age;
  1047. }
  1048. public function test(){
  1049. dump(ROOT_PATH);
  1050. dump(parse_url('https://lh.hdlkeji.com/uploads/20230221/0866987639c981b0f59dcc43cdffdc16_hr5n1hkhdap6gcadj63eh7vrmg.jpeg'));
  1051. }
  1052. /**
  1053. * 选号
  1054. * @ApiMethod (POST)
  1055. * @ApiParams (name=product_no,description=产品编码)
  1056. */
  1057. public function select_num_flow(){
  1058. $data = $this->_validate([
  1059. 'product_sku'=>['require'],
  1060. ]);
  1061. $list = GantanhaoService::getSelectNum($data['product_sku']);
  1062. $this->success('成功',$list);
  1063. }
  1064. }