MobileController.php 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  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. // 判断数据有无
  478. $mobile_ids = [];
  479. foreach ($esData['data'] as $dv){
  480. $mobile_ids[] = $dv['id'];
  481. }
  482. $mobile_db_ids=Mobile::whereIn('id',$mobile_ids)->column('id');
  483. // es 需要删除的id
  484. $mobile_ids_es_del = array_diff($mobile_ids,$mobile_db_ids);
  485. if($mobile_ids_es_del){
  486. EsMobileService::delMobiles($mobile_ids_es_del);
  487. user_log("EsMobileService_indexList_delByMobile", $mobile_ids_es_del);
  488. //foreach ($esData['data'] as $idk => $idv){
  489. // if(in_array($idv['id'],$mobile_ids_es_del)){
  490. // unset($esData['data'][$idk]);
  491. // }
  492. // }
  493. }
  494. $this->success('',$esData);
  495. }
  496. /**
  497. * 号码详情
  498. * @ApiParams (name=id,description=号码id)
  499. * @ApiReturnParams (name=copy_word,description=复制的内容)
  500. * @ApiReturnParams (name=card_status,description=1需上传三张身份证照片)
  501. */
  502. public function show(){
  503. $data=$this->_validate([
  504. 'id'=>['require']
  505. ]);
  506. $user=$this->auth->getUser();
  507. $mobile=Mobile::where('id','id')->with(['info'])->find($data['id']);
  508. if(!$mobile){
  509. EsMobileService::delMobiles([$data['id']]);
  510. $this->error('您查找的手机号已下架或不存在');
  511. }
  512. if($mobile['type']==1) {
  513. EsMobileService::addMobile($mobile);
  514. }
  515. //MobileUserHistory::add($user,$mobile);
  516. $mobile->addViewCount();
  517. $mobile->append(['view_count','copy_word']);
  518. $mobile->makeHidden();
  519. MobileInfo::makeFreeApp($mobile['info']);
  520. $this->success('',$mobile);
  521. }
  522. /**
  523. * 下单
  524. * @ApiMethod (POST)
  525. * @ApiParams (name=mobile_id,description=手机号ID)
  526. * @ApiParams (name=name,description=姓名)
  527. * @ApiParams (name=phone,description=手机号)
  528. * @ApiParams (name=sms_code,description=验证码)
  529. * @ApiParams (name=id_no,description="身份号码,450804198608275870",sample="450804198608275870")
  530. * @ApiParams (name=open_idcard_face_img,description="身份证正面照片",required=false)
  531. * @ApiParams (name=open_idcard_back_img,description="身份证反面照片",required=false)
  532. * @ApiParams (name=open_face_img,description="脸部照片",required=false)
  533. * @ApiParams (name=county,description="城市ID,区县id")
  534. * @ApiParams (name=address,description=详细地址)
  535. * @ApiParams (name=remark,description=备注)
  536. * @ApiParams (name=no,description=选号)
  537. * @ApiParams (name=pay_type,description="1微信2支付宝3京东4抖音小程序5快手小程序")
  538. * @ApiParams (name=return_url,description="支付完成回调页面链接")
  539. * @ApiParams (name=clickid,description="巨量引擎clickid")
  540. * @ApiReturnParams (name=pay_url,description="支付链接")
  541. * @ApiReturnParams (name=without_pay,description="是否不需要支付")
  542. * @ApiReturnParams (name=res,description="抖音支付时返回参数")
  543. */
  544. public function apply(){
  545. $needId=config('site.system_id_form_open')?true:false;
  546. $user=$this->auth->getUser();
  547. $data=$this->_validate([
  548. 'mobile_id'=>'require',
  549. 'name|姓名'=>['require','max:20'],
  550. 'phone|手机号'=>'require|mobile',
  551. //'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]$/'],
  552. 'county|地区'=>'require|integer',
  553. 'address|详细地址'=>['require','min:4', 'max:100'],
  554. ]);
  555. if($needId){
  556. $this->_validate([
  557. '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]$/'],
  558. ]);
  559. }
  560. Db::startTrans();
  561. $mobile=Mobile::lock(true)->findOrFail($data['mobile_id']);
  562. if($mobile['type']==1){
  563. $this->_validate([
  564. 'pay_type'=>'require|in:'.implode(',',array_keys(MobileOrder::$payTypes)),
  565. ]);
  566. }
  567. if($mobile['type'] == 2){
  568. $this->_validate([
  569. '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]$/'],
  570. ]);
  571. if($mobile['card_status']){
  572. $this->_validate([
  573. 'open_idcard_face_img|身份证正面照片' => 'require',
  574. 'open_idcard_back_img|身份证反面照片' => 'require',
  575. 'open_face_img|脸部照片' => 'require',
  576. ]);
  577. }
  578. $blackListConfig = config('site.flow_blacklist');
  579. if($blackListConfig){
  580. $blackList = [];
  581. $blackListTmp = explode("\r\n", $blackListConfig);
  582. foreach($blackListTmp as $key=>$val){
  583. $tmpId = explode(' ', $val);
  584. if(isset($tmpId[1]) && $tmpId[1]) $blackList[] = $tmpId[1];
  585. }
  586. if(in_array($data['id_no'], $blackList)) $this->error('该身份证号已被禁用');
  587. }
  588. $flowLimitAgeStart = $mobile['min_age'];
  589. $flowLimitAgeEnd = $mobile['max_age'];
  590. $birthDay = IdVerify::instance()->getBirthDay($data['id_no']);
  591. $age = $this->countAge($birthDay);
  592. if($flowLimitAgeStart && $age < $flowLimitAgeStart) $this->error('该身份证号年龄被限制');
  593. if($flowLimitAgeEnd && $age > $flowLimitAgeEnd) $this->error('该身份证号年龄被限制');
  594. if($mobile['send_template']){
  595. if(!Mobile::sendTemplateLimit($mobile, $data['county'])) $this->error('该地区暂不支持订购');
  596. }
  597. if($mobile['not_send_template']){
  598. if(Mobile::notSendTemplateLimit($mobile, $data['county'])) $this->error('该地区暂不支持订购');
  599. }
  600. }
  601. $mobile->shouldBuy();
  602. Area::shouldSend($data['county']);
  603. $system_sms_open = config('site.system_sms_open') ? true : false;
  604. if($system_sms_open && $mobile->needCheckSmsCode()) {
  605. SmsSend::setMobile($data['phone'])->setCode($data['sms_code'] ?? '')->setEvent('order')->check();
  606. }
  607. #禁止重复下单
  608. $hasOrder=MobileOrder::where('mobile_id',$mobile->id)
  609. ->where('phone',$data['phone'])
  610. ->where('create_time','>',time()-10)
  611. ->value('id');
  612. if($hasOrder){
  613. Db::rollback();
  614. $this->error('操作频繁');
  615. }
  616. // if($needId && Mobile::isType($mobile['type'])){
  617. if(Mobile::isType($mobile['type'])){
  618. // if($needId && !App::$debug) {
  619. if($needId || $mobile['type'] == 2) {
  620. IdVerify::instance()->check($data['name'] ?? '', $data['id_no'] ?? '');
  621. }
  622. if($mobile['type'] == 2){
  623. $orderLimit = config('site.'.$mobile['brand']);
  624. if($orderLimit && MobileOrder::orderLimit($data['id_no'], $orderLimit, $mobile['brand'])) $this->error('订购频繁');
  625. }
  626. //elseif(MobileOrder::hasOrdered($data['phone'],$mobile)){
  627. elseif(MobileOrder::hasOrdered($data['phone'],$mobile['brand'])){
  628. $this->error('订购频繁');
  629. }
  630. }
  631. $order = $data;
  632. $order['s_id']=getChanId();
  633. $order['admin_id'] = $mobile['proxy_id'];
  634. $order['no'] = array_key_exists('no',$data)?$data['no']:$mobile['no'];
  635. $order['city'] = implode(',', Area::getTreeId($data['county']));
  636. $order['amount_original'] = $mobile['amount_original'];
  637. $order['amount_hd'] = $mobile['amount'];
  638. $order['amount_charge'] = $mobile['amount_charge'];
  639. $order['amount'] = $mobile['amount'];
  640. $order['amount_di'] = $mobile['amount_di'];
  641. $order['amount_base'] = bcsub($mobile['amount'],$mobile['amount_charge']);
  642. $order['type'] = $mobile['type'];
  643. $order['status'] = 0;
  644. if($user){
  645. $order['user_id']=$user['id'];
  646. }
  647. unset($order['county'], $order['sms_code']);
  648. $mobileOrder = (new MobileOrder);
  649. if($mobile['type']==2){
  650. $mobileOrder->flowOrderSubmit();
  651. }
  652. $mobileOrder->allowField(true)->save($order);
  653. //$succ=$mobileOrder;
  654. //if($mobile['type']==1) {
  655. $succ = $this->pay($mobileOrder, $data);
  656. //}
  657. #下架号码
  658. /*$mobile['status']=$mobile::S_DOWN;
  659. $mobile->save();*/
  660. Db::commit();
  661. $this->success('', $succ);
  662. }
  663. protected function pay(MobileOrder $mobileOrder,$data,$is_continue=false){
  664. $params = input('param.');
  665. $clickid = $params['clickid'] ?? '';
  666. $data['return_url']=h5_link('pages/PaySuccess/PaySuccess?id='.$mobileOrder['id']);
  667. // if($mobileOrder['type']==2){
  668. // OceanEngineService::setQuery(['clickid'=>input('clickid')])->setAddon(['order_no'=>input('clickid')])->form();
  669. // }
  670. $succ=[
  671. 'pay_url'=>'',
  672. 'id'=>$mobileOrder['id'],
  673. 'without_pay'=>0,
  674. 'res'=>null,
  675. ];
  676. if($mobileOrder['amount']==0){
  677. $succ['without_pay']=1;
  678. $mobileOrder->paySuccessCallback();
  679. try {
  680. OceanEngineService::setQuery(['clickid'=>$clickid])->setAddon(['order_no'=>$clickid])->shopping();
  681. GantanhaoService::orderPurchase($mobileOrder);
  682. }catch (\Exception $e){}
  683. return $succ;
  684. }
  685. $payment=Payment::create([
  686. 'order_no'=>session_create_id(),
  687. 'amount'=>$mobileOrder['amount'],
  688. 'mobile_order_id'=>$mobileOrder['id'],
  689. 'params'=>[
  690. 'clickid'=>$clickid,
  691. ]
  692. ]);
  693. $filename=session_create_id(date('Ymd'));
  694. if(!is_dir($dir=RUNTIME_PATH.'/payment/')) {
  695. @mkdir($dir, 0777, true);
  696. }
  697. if($data['pay_type']==1){
  698. $info=Service::submitOrder($payment['amount'],
  699. $payment['order_no'],'wechat',"购买手机号{$mobileOrder['no']}",
  700. Service::notifyUrl('wechat',$payment['order_no']),$data['return_url']??'','wap');
  701. file_put_contents(RUNTIME_PATH.'/payment/'.$filename,$info->getContent());
  702. $succ['pay_url']=url('/index/index/payment/a/'.$filename,[],true,true);
  703. }elseif ($data['pay_type']==2){
  704. $info=Service::submitOrder($payment['amount'],
  705. $payment['order_no'],'alipay',"购买手机号{$mobileOrder['no']}",
  706. Service::notifyUrl('alipay',$payment['order_no']),$data['return_url']??'','wap');
  707. file_put_contents(RUNTIME_PATH.'/payment/'.$filename,view('alipay',['form'=>$info->getContent()])->getContent());
  708. $succ['pay_url']=url('/index/index/payment/a/'.$filename,[],true,true);
  709. }elseif ($data['pay_type']==3){
  710. $jdpay=App::invokeClass(Jdpay::class);
  711. $payData=$jdpay->order($payment['order_no'],$payment['amount'],"购买手机号{$mobileOrder['no']}");
  712. $succ=array_merge($succ,$payData);
  713. }elseif ($data['pay_type']==4){
  714. $payData=ByteDancePay::setInfo($payment['order_no'],$payment['amount'],"购买手机号{$mobileOrder['no']}")->get();
  715. $succ['res']=$payData;
  716. if(!$is_continue) {
  717. $push = new ByteDanceOrderPush();
  718. $push->setOrder($mobileOrder);
  719. $push->setPayment($payment);
  720. $push->get();
  721. }
  722. }elseif ($data['pay_type']==5){
  723. $getData['access_token'] = $this->_getKsAccessToken();
  724. $getData['app_id'] = config('kuaishou.appid');
  725. $user=$this->auth->getUser();
  726. $postData['open_id'] = Db('user')->where(['id'=>$user['id']])->value('k_openid'); //用户的openid
  727. $postData['out_order_no'] = $payment['order_no'];
  728. // $postData['total_amount'] = $payment['amount'];
  729. $postData['total_amount'] = $payment['amount']*100;
  730. $postData['subject'] = "购买手机号{$mobileOrder['no']}";
  731. $postData['detail'] = "购买手机号{$mobileOrder['no']}";
  732. // $postData['attach'] = 'asdfasdf';
  733. $postData['type'] = 1856;
  734. $postData['expire_time'] = 172800;
  735. $postData['notify_url'] =request()->domain()."/index/payment/notify_ks/order_no/{$payment['order_no']}";
  736. $sign = _makeKsSgin($getData, $postData);
  737. $postData['sign'] = $sign;
  738. $url = 'https://open.kuaishou.com/openapi/mp/developer/epay/create_order?' . http_build_query($getData);
  739. $json = json_encode($postData, 320);
  740. $res = jsonPost($url, $json);
  741. $resArr=json_decode($res,true);
  742. if(!is_array($resArr)){
  743. $this->error('请求支付失败');
  744. }
  745. if($resArr['result']!=1){
  746. $this->error($resArr['error_msg'],$postData);
  747. }
  748. $succ['res']=$resArr['order_info'];
  749. }
  750. return $succ;
  751. }
  752. private function _getKsAccessToken() {
  753. return AccessToken::get();
  754. }
  755. /**
  756. * 继续支付
  757. * @ApiParams (name=id,description=订单id)
  758. * @ApiParams (name=pay_type,description=支付方式与下单一样)
  759. * @ApiParams (name=return_url,description="支付完成回调页面链接")
  760. */
  761. public function continue_pay(){
  762. $data=$this->_validate([
  763. 'id'=>['require'],
  764. 'pay_type'=>'require|in:'.implode(',',array_keys(MobileOrder::$payTypes)),
  765. ]);
  766. $mobileOrder=MobileOrder::whereNull('pay_time')->findOrFail($data['id']);
  767. $mobileOrder->continuePay();
  768. $succ=$this->pay($mobileOrder,$data,true);
  769. $this->success('',$succ);
  770. }
  771. /**
  772. * 订单详情
  773. * @ApiParams (name=id,description=订单id)
  774. * @ApiReturnParams (name=no,description=手机号)
  775. * @ApiReturnParams (name=order_no,description=订单号)
  776. * @ApiReturnParams (name=amount_hd,description=活动价)
  777. * @ApiReturnParams (name=amount_original,description=原价)
  778. * @ApiReturnParams (name=amount_charge,description=预充)
  779. * @ApiReturnParams (name=describe,description=套餐说明)
  780. * @ApiReturnParams (name=proxy.wx_qr,description=客服二维码)
  781. * @ApiReturnParams (name=name,description=收货人)
  782. * @ApiReturnParams (name=phone,description=收货人手机号)
  783. * @ApiReturnParams (name=id_no,description=收货人身份证)
  784. * @ApiReturnParams (name=address,description=收货地址)
  785. * @ApiReturnParams (name=remark,description=备注)
  786. * @ApiReturnParams (name=create_time,description=下单时间)
  787. * @ApiReturnParams (name=amount,description=订单金额)
  788. * @ApiReturnParams (name=trans_name,description=快递名称)
  789. * @ApiReturnParams (name=trans_no,description=快递单号)
  790. * @ApiReturnParams (name=status,description="0=>'待付款',10=>'已付款',15=>'待发货',17=>'有号码未发货',20=>'待开卡',25=>'已完成',30=>'申请退款',50=>'已关闭',60=>'无号码',70=>'换卡',80=>'争议单',90=>'已退款',100=>'退款驳回',110=>'审核失败'")
  791. * @ApiReturnParams (name=reason,description="状态为110审核失败时,敢探号审核失败原因")
  792. * @ApiReturnParams (name=open_uploaded,description=是否已上传开卡资料)
  793. * @ApiReturnParams (name=open_idcard_face_img,description=身份证正面照)
  794. * @ApiReturnParams (name=open_idcard_back_img,description=身份证反面照)
  795. * @ApiReturnParams (name=open_face_img,description=头像照)
  796. * @ApiReturnParams (name=open_name,description=姓名)
  797. * @ApiReturnParams (name=open_id_no,description=身份证号码)
  798. * @ApiReturnParams (name=open_phone,description=手机号)
  799. * @ApiReturnParams (name=pay_time,description=支付时间)
  800. * @ApiReturnParams (name=expire_time,description=过期时间)
  801. */
  802. public function order_detail(){
  803. $order = MobileOrder::with(['proxy','info'])->findOrFail(input('id'));
  804. $order['proxy'] && $order['proxy']->hidden(['password']);
  805. $order['describe'] = $order['info']['info']['describe']??'';
  806. $reason = $order['gantanhao_data_notify'] ? json_decode($order['gantanhao_data_notify'], true) : '';
  807. $order['reason'] = $reason ? $reason['reason'] : '';
  808. $this->success('',$order);
  809. }
  810. /**
  811. * 订单列表
  812. * @ApiParams (name=page,description=page)
  813. * @ApiParams (name=limit,description=limit)
  814. * @ApiParams (name=phone,description="手机号,小程序可不传")
  815. * @ApiParams (name=type,description=1靓号2流量卡)
  816. * @ApiParams (name=status,description="状态:0待付款10:已付款15:待发货17:有号码未发货20:待开卡25:已完成30:申请退款50:已关闭60:无号码70:换卡80:争议单90:已退款100:退款驳回110:审核失败")
  817. * @ApiSummary (流量卡状态15:已提运营25:已完成)
  818. */
  819. public function order_list(){
  820. $user=$this->auth->getUser();
  821. $data=input();
  822. $this->_validate([
  823. 'type|类型'=>['in:1,2'],
  824. ]);
  825. if(!$user){
  826. $this->_validate([
  827. 'phone|手机号'=>['require'],
  828. ]);
  829. }
  830. $type=$data['type']??1;
  831. $type=$type?:1;
  832. $order=MobileOrder::with(['proxy','info'])
  833. ->where(function ($q)use ($user,$data){
  834. if(!empty($data['phone'])){
  835. $q->where('phone',$data['phone']);
  836. }elseif ($user){
  837. $q->where('user_id',$user['id']);
  838. }else{
  839. $q->where('id',1);
  840. }
  841. })
  842. ->filterShow($type)
  843. ->where('type',$type)
  844. ->order('id','desc');
  845. if(isset($data['status']) && $data['status']!==''){
  846. if($data['status']==0){
  847. $status=[
  848. $data['status'],17,60,70,80,
  849. ];
  850. $order->whereIn('status',$status);
  851. }else {
  852. $order->where('status', $data['status']);
  853. }
  854. }
  855. $ret=$order->paginate(input('limit',15));
  856. $this->success('',$ret);
  857. }
  858. /**
  859. * 筛选配置
  860. *
  861. */
  862. public function config(){
  863. $config=[];
  864. $networks=MobileConstant::getNetworkString();
  865. $config['network']=$networks;
  866. $config['rule']=MobileConstant::getRuleKeys();
  867. $this->success('',$config);
  868. }
  869. /**
  870. * 上传开卡资料
  871. * @ApiParams (name=id,description=订单id)
  872. * @ApiParams (name=idcard_face_img,description=身份证正面照片)
  873. * @ApiParams (name=idcard_back_img,description=身份证反面照片)
  874. * @ApiParams (name=face_img,description=本人照片)
  875. * @ApiParams (name=name,description=本人姓名)
  876. * @ApiParams (name=id_no,description=本人身份证号码)
  877. * @ApiParams (name=phone,description=本人联系电话)
  878. */
  879. public function upload_identity(){
  880. $data=$this->_validate([
  881. 'id'=>['require'],
  882. 'idcard_face_img|身份证正面照片'=>['require','url'],
  883. 'idcard_back_img|身份证反面照片'=>['require','url'],
  884. 'face_img|本人照片'=>['require','url'],
  885. 'name|本人姓名'=>['require','max:10'],
  886. 'id_no|本人身份证号码'=>['require'],
  887. 'phone|本人联系电话'=>['require','integer'],
  888. ]);
  889. $order=MobileOrder::findOrFail($data['id']);
  890. if($order['open_uploaded']){
  891. $this->error('请勿再次上传');
  892. }
  893. IdVerify::instance()->check($data['name'],$data['id_no']);
  894. $order['open_uploaded']=1;
  895. $order['open_idcard_face_img']=$data['idcard_face_img'];
  896. $order['open_idcard_back_img']=$data['idcard_back_img'];
  897. $order['open_face_img']=$data['face_img'];
  898. $order['open_name']=$data['name'];
  899. $order['open_id_no']=$data['id_no'];
  900. $order['open_phone']=$data['phone'];
  901. if(!$order->save()){
  902. $this->error('保存失败');
  903. }
  904. $this->success('');
  905. }
  906. /**
  907. * 预定号码
  908. * @ApiParams (name=no,description=号码)
  909. * @ApiParams (name=price_min,description=最低承受价格)
  910. * @ApiParams (name=price_max,description=最高承受价格)
  911. * @ApiParams (name=remark,description=备注)
  912. * @ApiParams (name=name,description=姓名)
  913. * @ApiParams (name=phone,description=联系电话)
  914. * @ApiParams (name=county,description=区县ID)
  915. * @ApiParams (name=address,description=详细地址)
  916. */
  917. public function order_no(){
  918. $data=$this->_validate([
  919. 'no|预定号码'=>['require','integer','min:3','max:8'],
  920. //'price_min'=>['require','integer','min:0'],
  921. 'price_max|可承受价格'=>['require','integer','min:0'],
  922. 'name|姓名'=>['require'],
  923. 'phone|联系电话'=>['require','integer','length:11'],
  924. 'county|城市'=>['require','integer'],
  925. 'address|详细地址'=>['require','length:0,250'],
  926. ]);
  927. $no=new MobileOrderNo;
  928. $data['city']=implode(',',Area::getTreeId($data['county']));
  929. $no->allowField(true)->save($data);
  930. $this->success('');
  931. }
  932. /**
  933. * 横幅播报
  934. * @ApiReturnParams (name=ordered_num,description=已订购人数)
  935. * @ApiReturnParams (name=no,description=号码)
  936. * @ApiReturnParams (name=name,description=人名)
  937. * @ApiReturnParams (name=num,description=人数)
  938. */
  939. public function ordered_show(){
  940. $data=[];
  941. $data['ordered_num']=SysConfig::look('mo_ordered_num',0);
  942. $data['ordered_list']=AdIndexOrderedFlow::field('name,no,num')
  943. ->order('num','asc')
  944. ->select();
  945. foreach ($data['ordered_list'] as $item){
  946. $item['no']=substr($item['no'],0,3).'****'.substr($item['no'],7,4);
  947. $item['name']=mb_substr($item['name'],0,mb_strlen($item['name'])-1).'*';
  948. }
  949. $this->success('',$data);
  950. }
  951. /**
  952. * 退款
  953. * @ApiMethod (POST)
  954. * @ApiParams (name=id,description=订单id)
  955. * @ApiParams (name=reason,description=退款原因)
  956. */
  957. public function refund(){
  958. $data=$this->_validate([
  959. 'id'=>'require',
  960. 'reason'=>'require|max:250',
  961. ]);
  962. Db::startTrans();
  963. $order=MobileOrder::lock(true)->findOrFail($data['id']);
  964. $order->checkAllowRefund();
  965. $order->makeUserRefund($data['reason']);
  966. Db::commit();
  967. $this->success();
  968. }
  969. /**
  970. * 查询物流
  971. * @ApiMethod (POST)
  972. * @ApiParams (name=id,description=订单id)
  973. * @ApiReturnParams (name=AcceptTime,description=时间)
  974. * @ApiReturnParams (name=AcceptStation,description=描述)
  975. */
  976. public function logistics(){
  977. $data=$this->_validate([
  978. 'id'=>['require'],
  979. ]);
  980. $order=MobileOrder::findOrFail($data['id']);
  981. $logistics=[];
  982. if(!$order['trans_id']||!$order['trans_no']){
  983. $this->success('',$logistics);
  984. }
  985. $logistics=TransferCheck::instance()->setNo($order['trans_no'])->setLogisticsCompany(LogisticsCompany::get($order['trans_id']))->setPhone($order['phone'])->setName($order['name'])->get();
  986. $this->success('',$logistics);
  987. }
  988. /**
  989. * 预占号码
  990. * @ApiParams (name=id,description=号码ID)
  991. * @ApiParams (name=chanId,description=通道ID)
  992. */
  993. public function take(){
  994. $data=$this->_validate([
  995. 'id|号码'=>['require','gt:0'],
  996. ]);
  997. $open=config('site.auto_take_open');
  998. $discount=config('site.auto_take_discount');
  999. if(!$open){
  1000. $this->success('未开启');
  1001. }
  1002. if($discount<=0||$discount>10){
  1003. $this->success('参数错误');
  1004. }
  1005. Db::startTrans();
  1006. $mobile=Mobile::lock(true)->findOrFail($data['id']);
  1007. if($mobile['is_activity']){
  1008. Db::rollback();
  1009. $this->success('已开启');
  1010. }
  1011. $chanId=getChanId();
  1012. $amount_kill=bcmul($mobile['amount_base'],$discount/10,0);
  1013. $mobile->makeActivity($amount_kill,$chanId);
  1014. Db::commit();
  1015. $this->success('改价成功');
  1016. }
  1017. /**
  1018. * 流量卡上传身份证照片
  1019. * @ApiMethod (POST)
  1020. * @ApiParams (name=id,description=订单id)
  1021. * @ApiParams (name=idcard_face_img,description=身份证正面照片)
  1022. * @ApiParams (name=idcard_back_img,description=身份证反面照片)
  1023. * @ApiParams (name=face_img,description=本人照片)
  1024. */
  1025. public function upload_identity_flow(){
  1026. $data = $this->_validate([
  1027. 'id'=>['require'],
  1028. 'idcard_face_img|身份证正面照片'=>['require','url'],
  1029. 'idcard_back_img|身份证反面照片'=>['require','url'],
  1030. 'face_img|本人照片'=>['require','url']
  1031. ]);
  1032. $order = MobileOrder::findOrFail($data['id']);
  1033. $dataGantanhao = $order['gantanhao_data'] ? json_decode($order['gantanhao_data'], true) : [];
  1034. if(!$dataGantanhao || !isset($dataGantanhao['str_rand']) || !$dataGantanhao['str_rand']){
  1035. $this->error('暂无法重新上传');
  1036. }
  1037. try{
  1038. GantanhaoService::orderPhotos($dataGantanhao['str_rand'], $data);
  1039. $order['open_idcard_face_img'] = $data['idcard_face_img'];
  1040. $order['open_idcard_back_img'] = $data['idcard_back_img'];
  1041. $order['open_face_img'] = $data['face_img'];
  1042. $order->save();
  1043. }
  1044. catch(\Exception $e){
  1045. if(stripos($e,'413')){
  1046. $this->error('图片过大');
  1047. }
  1048. Log::error("流量卡上传身份证照片:".json_encode($e));
  1049. $this->error('保存失败');
  1050. }
  1051. $this->success('上传成功');
  1052. }
  1053. /**
  1054. * 计算年龄
  1055. */
  1056. private function countAge($birthDay = ''){
  1057. if(!$birthDay) return false;
  1058. $age = strtotime($birthDay['year'].$birthDay['month'].$birthDay['day']);
  1059. if($age === false) return false;
  1060. list($y, $m, $d) = explode('-', date('Y-m-d'));
  1061. $age = $y - $birthDay['year'];
  1062. if((int)($m.$d) < (int)($birthDay['month'].$birthDay['day'])) $age -= 1;
  1063. return $age;
  1064. }
  1065. public function test(){
  1066. dump(ROOT_PATH);
  1067. dump(parse_url('https://lh.hdlkeji.com/uploads/20230221/0866987639c981b0f59dcc43cdffdc16_hr5n1hkhdap6gcadj63eh7vrmg.jpeg'));
  1068. }
  1069. /**
  1070. * 选号
  1071. * @ApiMethod (POST)
  1072. * @ApiParams (name=product_no,description=产品编码)
  1073. */
  1074. public function select_num_flow(){
  1075. $data = $this->_validate([
  1076. 'product_sku'=>['require'],
  1077. ]);
  1078. $list = GantanhaoService::getSelectNum($data['product_sku']);
  1079. $this->success('成功',$list);
  1080. }
  1081. }