MobileController.php 49 KB

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