Secondary.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. <?php
  2. namespace app\api\controller;
  3. use Alipay\EasySDK\Kernel\Util\ResponseChecker;
  4. use app\common\library\AliPay;
  5. use app\common\library\Shande;
  6. use EasyWeChat\Factory;
  7. use think\cache\driver\Redis;
  8. use think\Db;
  9. use think\Exception;
  10. use function EasyWeChat\Kernel\Support\get_client_ip;
  11. use function Symfony\Component\String\length;
  12. /**
  13. * @title 二级市场
  14. * @controller secondary
  15. * @package app\api\controller
  16. */
  17. class Secondary extends Base
  18. {
  19. public function initialize(){
  20. parent::initialize();
  21. parent::check_login();
  22. }
  23. /**
  24. * @title 藏品出售
  25. * @desc 藏品出售
  26. * @author Gavin
  27. * @url /api/Secondary/sell
  28. * @method POST
  29. * @header name:Authorization require:1 desc:Token
  30. *
  31. * @param name:id type:int require:1 default:1 desc:藏品ID
  32. * @param name:resale_price type:decimal require:1 default:1 desc:出售价格
  33. * @param name:second_password type:int require:1 default:-- desc:支付密码
  34. *
  35. */
  36. public function sell(){
  37. $this->checkSwitch(1);
  38. $id = input('id');
  39. //$this->error('暂时关闭');
  40. $user = getMemberInfoHash($this->uid); //获取用户信息
  41. if ($user['is_auth']==0) $this->error('请先实名认证!');
  42. $resale_price = input('resale_price');
  43. $second_password = input('second_password');
  44. if (!$id || !$resale_price) $this->error('参数错误');
  45. //if ($resale_price<'1') $this->error('最低1元');
  46. if ($resale_price<'0.1') $this->error('最低0.1元');
  47. if ($resale_price>'99999') $this->error('最高99999元');
  48. $info = Db::name('store_order_info')
  49. ->where('mid',$this->uid)
  50. ->where('id',$id)
  51. ->find();
  52. if (!$info || $info['status']==2) $this->error('藏品不存在');
  53. if ($info['resale_status']!=1) $this->error('挂售状态错误');
  54. if ($user['second_password']!=md5($second_password)) $this->error('密码错误');
  55. $update_data = [
  56. 'resale_status'=>2,
  57. 'resale_time'=>date('Y-m-d H:i:s'),
  58. 'resale_price'=>$resale_price
  59. ];
  60. if (Db::name('store_order_info')->where('id',$id)->update($update_data)){
  61. $this->success('成功');
  62. }
  63. $this->error('失败');
  64. }
  65. /**
  66. * @title 藏品取消出售
  67. * @desc 藏品取消出售
  68. * @author Gavin
  69. * @url /api/Secondary/cancel_sell
  70. * @method POST
  71. * @header name:Authorization require:1 desc:Token
  72. *
  73. * @param name:id type:int require:1 default:1 desc:藏品ID
  74. */
  75. public function cancel_sell(){
  76. $this->checkSwitch(1);
  77. $id = input('id');
  78. if (!$id) $this->error('参数错误');
  79. $info = Db::name('store_order_info')
  80. ->where('mid',$this->uid)
  81. ->where('id',$id)
  82. ->find();
  83. if (!$info || $info['status']==2) $this->error('藏品不存在');
  84. if ($info['resale_status']!=2) $this->error('挂售状态错误');
  85. //判断是否有待支付订单
  86. $count = Db::name('store_order_info_order')->where('info_id',$id)->where('status',0)->count();
  87. if ($count) $this->error('支付中,无法取消');
  88. $update_data = [
  89. 'resale_status'=>1,
  90. ];
  91. if (Db::name('store_order_info')->where('id',$id)->update($update_data)){
  92. $this->success('成功');
  93. }
  94. $this->error('失败');
  95. }
  96. /**
  97. * @title 标签列表
  98. * @desc 标签列表
  99. * @author Gavin
  100. * @url /api/Secondary/label_list
  101. * @method POST
  102. * @header name:Authorization require:1 desc:Token
  103. */
  104. public function label_list(){
  105. $list = Db::name('store_collection')->whereNotIn('label','测试,测试勿拍')->group('label')->column('label');
  106. $list = array_merge(['全部'],$list);
  107. $this->success('成功',['label_list'=>$list]);
  108. }
  109. /**
  110. * @title 二级市场列表
  111. * @desc 二级市场列表
  112. * @author Gavin
  113. * @url /api/Secondary/sell_list
  114. * @method POST
  115. * @header name:Authorization require:1 desc:Token
  116. * @param name:page type:int : default:1 desc:页数
  117. * @param name:page_num type:int : default:20 desc:每页数
  118. *
  119. * @param name:keyword type:string require:0 default: desc:关键词
  120. * @param name:label type:string require:0 default: desc:标签
  121. * @param name:time_order type:string require:0 default: desc:时间排序(asc:正序desc:倒序)
  122. * @param name:price_order type:string require:0 default: desc:价格排序(asc:正序desc:倒序)
  123. *
  124. * @return name:name type:string require:0 default:0 desc:藏品名称
  125. * @return name:cover type:string require:0 default:0 desc:图片
  126. * @return name:member_name type:string require:0 default:0 desc:出售人名称
  127. * @return name:member_headimg type:string require:0 default:0 desc:出售人头像
  128. * @return name:resale_price type:string require:0 default:0 desc:出售价格
  129. */
  130. public function sell_list(){
  131. $keyword = input('keyword');
  132. $label = input('label');
  133. $time_order = input('time_order');
  134. $price_order = input('price_order');
  135. $count = Db::name('store_order_info')
  136. ->where('status','neq',2)
  137. ->where('resale_status',2)
  138. ->where('is_destruction',1)
  139. ->when($keyword,function ($query) use ($keyword){
  140. $query->whereLike('name','%'.$keyword.'%');
  141. })
  142. ->when($label,function ($query) use ($label){
  143. if ($label!='全部'){
  144. $ids = Db::name('store_collection')->where('label',$label)->column('id');
  145. $query->whereIn('c_id',$ids);
  146. }
  147. })
  148. ->count();
  149. $list = Db::name('store_order_info')
  150. ->where('status','neq',2)
  151. ->where('resale_status',2)
  152. ->where('is_destruction',1)
  153. ->when($keyword,function ($query) use ($keyword){
  154. $query->whereLike('name','%'.$keyword.'%');
  155. })
  156. ->when($label,function ($query) use ($label){
  157. if ($label!='全部'){
  158. $ids = Db::name('store_collection')->where('label',$label)->column('id');
  159. $query->whereIn('c_id',$ids);
  160. }
  161. })
  162. ->when($price_order,function ($query) use ($price_order){
  163. $query->order('resale_price '.$price_order);
  164. })
  165. ->when($time_order,function ($query) use ($time_order){
  166. $query->order('resale_time '.$time_order);
  167. })
  168. ->limit($this->off_set,$this->page_num)
  169. ->select();
  170. foreach ($list as &$v){
  171. $member = getMemberInfoHash($v['mid']); //获取用户信息
  172. $v['member_name'] = $member['name'];
  173. $v['member_headimg'] = $member['headimg'];
  174. $v['pro_info'] = json_decode($v['pro_info'],true);
  175. $count = Db::name('store_order_info_order')->where('info_id',$v['id'])->where('status',0)->count();
  176. $v['is_buy'] = $count>0 ? 1 : 0;
  177. }
  178. $this->success('成功',compact('count','list'));
  179. }
  180. /**
  181. * @title 二级市场详情
  182. * @desc 二级市场详情
  183. * @author Gavin
  184. * @url /api/Secondary/sell_list_detail
  185. * @method POST
  186. * @header name:Authorization require:1 desc:Token
  187. * @param name:id type:int : default: desc:id
  188. * @return name:id type:int require:0 default:0 desc:藏品ID
  189. * @return name:tag type:string require:0 default:0 desc:唯一标签
  190. * @return name:collectors_name type:string require:0 default:0 desc:收藏者
  191. * @return name:collectors_hash type:string require:0 default:0 desc:收藏者hash
  192. * @return name:create_at type:string require:0 default:0 desc:收藏时间
  193. * @return name:company type:string require:0 default:0 desc:流转公司
  194. * @return name:company_hash type:string require:0 default:0 desc:流转公司hash
  195. * @return name:resale_status type:string require:0 default:0 desc:1:未挂售2挂售中3已出售
  196. * @return name:resale_price type:float require:0 default:0 desc:二级市场挂售价格
  197. * @return name:pro_info@name type:string require:0 default:0 desc:藏品名称
  198. * @return name:pro_info@price type:string require:0 default:0 desc:藏品价格
  199. * @return name:pro_info@label type:string require:0 default:0 desc:藏品标签
  200. * @return name:pro_info@cover type:string require:0 default:0 desc:藏品图片
  201. * @return name:pro_info@auth_img type:string require:0 default:0 desc:作者头像
  202. * @return name:pro_info@auth_name type:string require:0 default:0 desc:作者姓名
  203. * @return name:pro_info@warm_prompt type:string require:0 default:0 desc:温馨提示
  204. * @return name:pro_info@share_img type:string require:0 default:0 desc:分享二维码
  205. * @return name:member_name type:string require:0 default:0 desc:用户名
  206. * @return name:member_headimg type:string require:0 default:0 desc:用户头像
  207. * @return name:is_buy type:int require:0 default:0 desc:是否可以购买【1是0否】
  208. */
  209. public function sell_list_detail(){
  210. $id = input('id');
  211. if (!$id) $this->error('参数错误');
  212. $info = Db::name('store_order_info')
  213. ->where('status','neq',2)
  214. ->where('resale_status',2)
  215. ->where('is_destruction',1)
  216. ->where('id',$id)
  217. ->find();
  218. if (!$info) $this->error('藏品不存在');
  219. $member = getMemberInfoHash($info['mid']); //获取用户信息
  220. $info['member_name'] = $member['name'];
  221. $info['member_headimg'] = $member['headimg'];
  222. $info['pro_info'] = json_decode($info['pro_info'],true);
  223. //判断是否有待支付订单
  224. $count = Db::name('store_order_info_order')->where('info_id',$id)->where('status',0)->count();
  225. $info['is_buy'] = $count>0 ? 1 : 0;
  226. $this->success('成功',$info);
  227. }
  228. /**
  229. * @title 购买
  230. * @desc 购买
  231. * @author Gavin
  232. * @url /api/Secondary/createOrder
  233. * @method POST
  234. * @header name:Authorization require:1 desc:Token
  235. * @param name:id type:int require:1 default: desc:主键ID
  236. * @param name:pay_type type:string require:1 default:wx desc:wx:微信zfb:支付宝sd:杉德h5,wallet余额
  237. * @param name:from type:string require:1 default:wx desc:wx:微信公众号h5:网页
  238. *
  239. * @return name:order_no type:int require:0 default:0 desc:订单号
  240. * @return name:pay type:string require:0 default:0 desc:支付信息
  241. */
  242. public function createOrder(){
  243. if (redisSetNx('SecondaryCreateOrder'.$this->uid,3)) {
  244. $this->checkSwitch(1);
  245. $id = input('id');
  246. $orderinfoid = input('id');
  247. //redis原子锁
  248. if (redisSetNx('SecondaryOrderCid'.$orderinfoid,20)) {
  249. $pay_type = input('pay_type','wx');
  250. $this->checkSwitch(2,$pay_type);
  251. $from = input('from','wx');
  252. $user = getMemberInfoHash($this->uid); //获取用户信息
  253. if (!$id) $this->error('参数错误');
  254. if ($user['is_auth']==0) $this->error('请先实名认证!');
  255. $info = Db::name('store_order_info')->where('id',$id)->find();
  256. if (!$info) $this->error('藏品不存在');
  257. if ($info['resale_status']==3) $this->error('藏品已出售');
  258. if ($info['resale_status']==1) $this->error('藏品已撤销出售');
  259. if ($info['mid']==$this->uid) $this->error('不能购买自己出售的藏品');
  260. if (isset($user['buy_time']) && $user['buy_time']>date('Y-m-d H:i:s')) $this->error('一小时取消3次以上,24小时内禁止下单');
  261. //判断是否有未支付订单
  262. $order_count = Db::name('store_order_info_order')->where('mid',$this->uid)->where('status',0)->count();
  263. if ($order_count) $this->error('有未支付订单,无法下单');
  264. //判断是否有待支付订单
  265. $count = Db::name('store_order_info_order')->where('info_id',$id)->where('status',0)->count();
  266. if ($count) $this->error('支付中,无法下单');
  267. $service_fee = getConfigValue('service_fee');
  268. $royalties = getConfigValue('royalties');
  269. $com = true;
  270. $error_msg = '失败,请稍后重试';
  271. Db::startTrans();
  272. try {
  273. $order_no = get_order_sn();
  274. //获取价格
  275. $price = $info['resale_price'];
  276. $num = 1;
  277. $discount = getMemberServiceCharge($this->uid);// 折扣
  278. $proportion = sprintf("%.2f",$price *($service_fee/100) * $discount); //四舍五入保留两位小数点
  279. $roya = sprintf("%.2f",$price *($royalties/100) * $discount); //四舍五入保留两位小数点
  280. $total_fee = bcmul($price,$num,2);
  281. $real_money = $price-$proportion-$roya;
  282. if($pay_type == 'wallet' && $user['money'] < $total_fee) throw new Exception('余额不足');
  283. $data = [
  284. 'order_no'=>$order_no,
  285. 'mid'=>$this->uid,
  286. 'info_id'=>$id,
  287. 'num'=>$num,
  288. 'pro_info'=>json_encode($info,true),
  289. 'pay_price'=>$total_fee,
  290. 'service_fee'=>$service_fee,
  291. 'royalties'=>$royalties,
  292. 'to_account'=>$real_money,
  293. 'pay_type'=>$pay_type
  294. ];
  295. $id = Db::name('store_order_info_order')->insertGetId($data);
  296. $body = '象链数藏购买二级市场藏品';
  297. switch ($pay_type){
  298. case 'wx':
  299. $config = retrunWxConfig();
  300. $total_fee = $total_fee * 100;
  301. $config['notify_url'] = 'https://'.$_SERVER['HTTP_HOST'].'/index.php/api/Pay/SecondaryWxOrderNotify';
  302. $app = Factory::payment($config);
  303. $post_data = [
  304. 'body' => $body,
  305. 'out_trade_no' => $order_no,
  306. 'total_fee' => $total_fee,
  307. 'attach'=>$this->uid, //自定义传值
  308. ];
  309. //trade_type SAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
  310. if ($from=='wx'){
  311. $post_data['openid'] = $user['openid'];
  312. $post_data['trade_type'] = 'JSAPI';
  313. }elseif ($from=='h5'){
  314. $post_data['trade_type'] = 'MWEB';
  315. }
  316. $result = $app->order->unify($post_data);
  317. if ($result['return_msg']=='OK'){
  318. if ($result['result_code']=='FAIL'){
  319. $com = false;
  320. Db::rollback();
  321. }else{
  322. $order1 = $app->jssdk->bridgeConfig($result['prepay_id']);//执行二次签名返回参数
  323. $retrun_data['order_no'] = $order_no;
  324. $retrun_data['id'] = $id;
  325. $retrun_data['pay'] = json_decode($order1,true);
  326. Db::commit();
  327. }
  328. }else{
  329. $com = false;
  330. Db::rollback();
  331. }
  332. break;
  333. case 'zfb':
  334. $zfb = new AliPay();
  335. $notify_url = 'https://'.$_SERVER['HTTP_HOST'].'/index.php/api/Pay/alipaySecondaryNotify';//回调地址
  336. $order = $zfb->ali_pay_pc($body, $total_fee, $order_no, $notify_url,'https://'.$_SERVER['HTTP_HOST'].'/h5/pages/shop/order');//调用支付宝支付的方法
  337. $retrun_data['order_no'] = $order_no;
  338. $retrun_data['id'] = $id;
  339. $retrun_data['pay'] = $order;
  340. Db::commit();
  341. break;
  342. case 'sd':
  343. $client = new Shande();
  344. $notify_url = 'https://'.$_SERVER['HTTP_HOST'].'/api/Pay/shandeSecondaryNotify';//回调地址
  345. $total_fee = $total_fee*100;
  346. $lenth = strlen($total_fee);
  347. $total_fee = get0number($lenth).$total_fee;
  348. $result = $client->orderPay($order_no,$total_fee,$body,$notify_url,'https://'.$_SERVER['HTTP_HOST'].'/h5/pages/shop/order',$user['bank_num']);
  349. $retrun_data['order_no'] = $order_no;
  350. $retrun_data['id'] = $id;
  351. $retrun_data['pay'] = json_decode($result['data'],true);
  352. Db::commit();
  353. break;
  354. }
  355. }catch (\Exception $e){
  356. $com=false;
  357. $error_msg = $e->getMessage();
  358. Db::rollback();
  359. }
  360. DelRedisSetNx('SecondaryCreateOrder' . $this->uid);
  361. DelRedisSetNx('SecondaryOrderCid'.$orderinfoid);
  362. if ($com) $this->success('成功',$retrun_data);
  363. $this->error($error_msg);
  364. }else{
  365. $this->error('服务器繁忙,请稍后重试');
  366. }
  367. }else{
  368. $this->error('服务器繁忙,请稍后重试');
  369. }
  370. }
  371. /**
  372. * @title 二级市场我的转售列表
  373. * @desc 二级市场我的转售列表
  374. * @author Gavin
  375. * @url /api/Secondary/my_sell_list
  376. * @method POST
  377. * @header name:Authorization require:1 desc:Token
  378. * @param name:page type:int : default:1 desc:页数
  379. * @param name:page_num type:int : default:20 desc:每页数
  380. *
  381. * @param name:keyword type:string require:0 default: desc:关键词
  382. * @param name:time_order type:string require:0 default: desc:时间排序(asc:正序desc:倒序)
  383. * @param name:price_order type:string require:0 default: desc:价格排序(asc:正序desc:倒序)
  384. *
  385. * @return name:name type:string require:0 default:0 desc:藏品名称
  386. * @return name:cover type:string require:0 default:0 desc:图片
  387. * @return name:member_name type:string require:0 default:0 desc:出售人名称
  388. * @return name:member_headimg type:string require:0 default:0 desc:出售人头像
  389. * @return name:resale_price type:string require:0 default:0 desc:出售价格
  390. */
  391. public function my_sell_list(){
  392. $keyword = input('keyword');
  393. $time_order = input('time_order');
  394. $price_order = input('price_order');
  395. $count = Db::name('store_order_info')
  396. ->where('mid',$this->uid)
  397. ->where('resale_status','neq',1)
  398. ->when($keyword,function ($query) use ($keyword){
  399. $query->whereLike('name','%'.$keyword.'%');
  400. })
  401. ->count();
  402. $list = Db::name('store_order_info')
  403. ->where('mid',$this->uid)
  404. ->where('resale_status','neq',1)
  405. ->when($keyword,function ($query) use ($keyword){
  406. $query->whereLike('name','%'.$keyword.'%');
  407. })
  408. ->when($price_order,function ($query) use ($price_order){
  409. $query->order('resale_price '.$price_order);
  410. })
  411. ->when($time_order,function ($query) use ($time_order){
  412. $query->order('resale_time '.$time_order);
  413. })
  414. ->order('resale_status asc')
  415. ->limit($this->off_set,$this->page_num)
  416. ->select();
  417. foreach ($list as &$v){
  418. $member = getMemberInfoHash($v['mid']); //获取用户信息
  419. $v['member_name'] = $member['name'];
  420. $v['member_headimg'] = $member['headimg'];
  421. $v['pro_info'] = json_decode($v['pro_info'],true);
  422. }
  423. $this->success('成功',compact('count','list'));
  424. }
  425. /**
  426. * @title 二级市场订单【列表】
  427. * @desc 二级市场订单
  428. * @author Gavin
  429. * @url /api/Secondary/secondaryOrderList
  430. * @method POST
  431. * @header name:Authorization require:1 desc:Token
  432. * @param name:page type:int : default:1 desc:页数
  433. * @param name:page_num type:int : default:20 desc:每页数
  434. *
  435. * @param name:status type:int require:0 default:-1 desc:-1全部,0:待支付1:已购买2:转售中3:已转售
  436. *
  437. * @return name:name type:string require:0 default:0 desc:藏品名称
  438. * @return name:cover type:string require:0 default:0 desc:图片
  439. * @return name:status type:int require:0 default:0 desc:0:待支付1:已购买2:转售中3:已转售
  440. * @return name:member_name type:string require:0 default:0 desc:出售人名称
  441. * @return name:member_headimg type:string require:0 default:0 desc:出售人头像
  442. * @return name:pay_price type:string require:0 default:0 desc:出售价格(已购买、待支付使用)
  443. * @return name:resale_price type:string require:0 default:0 desc:出售价格(转售中、已转售使用)
  444. * @return name:cancel_time type:string require:0 default:0 desc:取消时间【status=0有用】
  445. * @return name:pro_info@name type:string default:-- desc:藏品名称
  446. * @return name:pro_info@price type:string default:-- desc:藏品价格
  447. * @return name:pro_info@cover type:string default:-- desc:藏品封面
  448. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  449. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  450. */
  451. public function secondaryOrderList(){
  452. $status = input('status',0);
  453. switch ($status){
  454. case 0:case 1:
  455. $count = Db::name('store_order_info_order')
  456. ->where('mid',$this->uid)
  457. ->where('status',$status)
  458. ->count();
  459. $list = Db::name('store_order_info_order')
  460. ->where('mid',$this->uid)
  461. ->where('status',$status)
  462. ->limit($this->off_set,$this->page_num)
  463. ->select();
  464. //自动取消分钟数
  465. $cancel_time = getCancelTime();
  466. foreach ($list as &$v){
  467. $v['pro_info'] = json_decode($v['pro_info'],true);
  468. $member = getMemberInfoHash($v['mid']); //获取用户信息
  469. $v['member_name'] = $member['name'];
  470. $v['member_headimg'] = $member['headimg'];
  471. if ($v['status']==0){
  472. $v['cancel_time'] = date('Y-m-d H:i:s',strtotime($v['create_at'])+($cancel_time*60));
  473. }
  474. }
  475. break;
  476. case 2:case 3:
  477. $count = Db::name('store_order_info')
  478. ->where('mid',$this->uid)
  479. ->where('resale_status',$status)
  480. ->where('is_destruction',1)
  481. ->count();
  482. $list = Db::name('store_order_info')
  483. ->where('mid',$this->uid)
  484. ->where('resale_status',$status)
  485. ->where('is_destruction',1)
  486. ->limit($this->off_set,$this->page_num)
  487. ->select();
  488. foreach ($list as &$v){
  489. $v['pro_info'] = json_decode($v['pro_info'],true);
  490. $member = getMemberInfoHash($v['mid']); //获取用户信息
  491. $v['member_name'] = $member['name'];
  492. $v['member_headimg'] = $member['headimg'];
  493. }
  494. break;
  495. default:
  496. $count = Db::name('store_order_info_order')
  497. ->where('mid',$this->uid)
  498. ->count();
  499. $list = Db::name('store_order_info_order')
  500. ->where('mid',$this->uid)
  501. ->limit($this->off_set,$this->page_num)
  502. ->select();
  503. $cancel_time = getCancelTime();
  504. foreach ($list as &$v){
  505. $v['pro_info'] = json_decode($v['pro_info'],true);
  506. $member = getMemberInfoHash($v['mid']); //获取用户信息
  507. $v['member_name'] = $member['name'];
  508. $v['member_headimg'] = $member['headimg'];
  509. if ($v['status']==0) $v['cancel_time'] = date('Y-m-d H:i:s',strtotime($v['create_at'])+($cancel_time*60));
  510. }
  511. break;
  512. }
  513. $this->success('成功',compact('count','list'));
  514. }
  515. /**
  516. * @title 二级市场订单【详情】
  517. * @desc 二级市场订单
  518. * @author Qc
  519. * @url /api/Secondary/secondaryOrderDetail
  520. * @method POST
  521. * @header name:Authorization require:1 desc:Token
  522. * @param name:id type:int require:0 default:-- desc:二级市场订单id
  523. * @return name:name type:string require:0 default:0 desc:藏品名称
  524. * @return name:cover type:string require:0 default:0 desc:图片
  525. * @return name:status type:int require:0 default:0 desc:0待支付,1已支付,2取消
  526. * @return name:pay_type type:string require:0 default:0 desc:支付方式:wx:微信zfb:支付宝wallet:余额
  527. * @return name:order_no type:string require:0 default:0 desc:单号
  528. * @return name:create_at type:string require:0 default:0 desc:下单时间
  529. *
  530. * @return name:pay_at type:string require:0 default:0 desc:支付时间
  531. * @return name:user_name type:string require:0 default:0 desc:售卖人名称
  532. * @return name:member_name type:string require:0 default:0 desc:买方名称
  533. * @return name:member_headimg type:string require:0 default:0 desc:买方头像
  534. * @return name:pay_price type:string require:0 default:0 desc:出售价格(已购买、待支付使用)
  535. * @return name:resale_price type:string require:0 default:0 desc:出售价格(转售中、已转售使用)
  536. * @return name:cancel_time type:string require:0 default:0 desc:取消时间【status=0有用】
  537. * @return name:pro_info@name type:string default:-- desc:藏品名称
  538. * @return name:pro_info@price type:string default:-- desc:藏品价格
  539. * @return name:pro_info@cover type:string default:-- desc:藏品封面
  540. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  541. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  542. */
  543. public function secondaryOrderDetail()
  544. {
  545. $detail = Db::name('store_order_info_order')->where('mid',$this->uid)->where('id',input('id'))->find();
  546. $member = getMemberInfoHash($detail['mid']); //获取用户信息
  547. $cancel_time = getCancelTime();
  548. $detail['member_name'] = $member['name'];
  549. $detail['member_headimg'] = $member['headimg'];
  550. if ($detail['status']==0) $detail['cancel_time'] = date('Y-m-d H:i:s',strtotime($detail['create_at'])+($cancel_time*60));
  551. $detail['pro_info'] = json_decode($detail['pro_info'],true);
  552. $sell_info = Db::name('store_order_info')->alias('o')
  553. ->field('o.*,m.name user_name,')
  554. ->where('o.id',$detail['info_id'])
  555. ->leftJoin('store_member m','m.id = o.mid')
  556. ->find();
  557. $detail['user_name'] = $sell_info['user_name'];
  558. $this->success('ok',['detail'=>$detail]);
  559. }
  560. /**
  561. * @title 取消订单
  562. * @desc 取消订单
  563. * @author Gavin
  564. * @url /api/Secondary/cancelOrder
  565. * @method POST
  566. * @header name:Authorization require:1 desc:Token
  567. * @param name:order_no type:string require:1 default:-- desc:订单号
  568. */
  569. public function cancelOrder(){
  570. $order_no = input('order_no');
  571. if (!$order_no) $this->error('参数错误');
  572. $order = Db::name('store_order_info_order')
  573. ->where('order_no',$order_no)
  574. ->where('mid',$this->uid)
  575. ->find();
  576. if (!$order) $this->error('订单不存在');
  577. if ($order['status']!=0) $this->error('订单已支付或已取消');
  578. $com = true;
  579. Db::startTrans();
  580. try {
  581. $up_data = [
  582. 'status'=>2,
  583. 'cancel_at'=>date('Y-m-d H:i:s'),
  584. 'cancel_state'=>2
  585. ];
  586. Db::name('store_order_info_order')->where('order_no',$order_no)->update($up_data);
  587. $cancle = [
  588. 'mid'=>$this->uid,
  589. 'order_id'=>$order['id']
  590. ];
  591. Db::name('store_order_info_cancel_log')->insert($cancle);
  592. $time = date('Y-m-d H:i:s',time()-(60*60));
  593. $count = Db::name('store_order_info_cancel_log')->where('mid',$this->uid)->where('create_at','gt',$time)->count();
  594. if ($count>2){
  595. $buy_time = date('Y-m-d H:i:s',time()+(24*60*60));
  596. Db::name('store_member')->where('id',$this->uid)->update(['buy_time'=>$buy_time]);
  597. }
  598. Db::commit();
  599. }catch (\Exception $e){
  600. $com=false;
  601. Db::rollback();
  602. }
  603. if ($com){
  604. setMemberInfoHash($this->uid);
  605. $this->success('取消成功');
  606. }else{
  607. $this->error('取消失败,请稍后重试');
  608. }
  609. }
  610. /**
  611. * @title 待支付订单支付
  612. * @desc 待支付订单支付
  613. * @author Gavin
  614. * @url /api/Secondary/payOrder
  615. * @method POST
  616. * @header name:Authorization require:1 desc:Token
  617. * @param name:order_no type:string require:1 default:-- desc:订单号
  618. * @param name:from type:string require:1 default:wx desc:wx:微信公众号h5:网页
  619. *
  620. * @return name:order_no type:int require:0 default:0 desc:订单号
  621. * @return name:pay type:string require:0 default:0 desc:支付信息
  622. * @return name:order_no type:string default:0 desc:支付单号(sd)
  623. * @return name:extend type:int default:0 desc:用户id(sd)
  624. * @return name:pay type:array default:0 desc:支付信息(sd)
  625. * @return name:pay.body type:array default:0 desc:支付信息(sd)
  626. * @return name:pay.totalAmount type:string default:0 desc:支付金额【000000010000是100元】(sd)
  627. * @return name:pay.orderCode type:string default:0 desc:支付单号(sd)
  628. * @return name:pay.credential type:string default:0 desc:正书(sd)
  629. */
  630. public function payOrder(){
  631. $this->checkSwitch(1);
  632. $user = getMemberInfoHash($this->uid); //获取用户信息
  633. $order_no = input('order_no'); //订单号
  634. $id = input('id');
  635. $from = input('from','wx');
  636. if (!$order_no) $this->error('参数错误');
  637. if (!$id) $this->error('参数错误');
  638. $order = Db::name('store_order_info_order')
  639. // ->where('order_no',$order_no)
  640. ->where('id',$id)
  641. ->where('mid',$this->uid)
  642. ->find();
  643. $order_no = $order['order_no'];
  644. $pay_type = $order['pay_type'];
  645. $this->checkSwitch(2,$pay_type);
  646. if (!$order) $this->error('订单不存在');
  647. if ($order['status']!=0) $this->error('订单已支付或已取消');
  648. $info = Db::name('store_order_info')->where('id',$order['info_id'])->find();
  649. if ($info['resale_status']!=2) $this->error('藏品已出售或已撤销出售');
  650. $com = true;
  651. $error_msg = '失败,请稍后重试';
  652. Db::startTrans();
  653. try {
  654. //获取价格
  655. $total_fee = $order['pay_price'];
  656. $body = '象链数藏购买二级市场藏品';
  657. switch ($pay_type){
  658. case 'wx':
  659. $config = retrunWxConfig();
  660. $total_fee = $total_fee * 100;
  661. $config['notify_url'] = 'https://'.$_SERVER['HTTP_HOST'].'/api/Pay/SecondaryWxOrderNotify';
  662. $app = Factory::payment($config);
  663. $post_data = [
  664. 'body' => $body,
  665. 'out_trade_no' => $order_no,
  666. 'total_fee' => $total_fee,
  667. 'attach'=>$this->uid, //自定义传值
  668. ];
  669. //trade_type SAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
  670. if ($from=='wx'){
  671. $post_data['openid'] = $user['openid'];
  672. $post_data['trade_type'] = 'JSAPI';
  673. }elseif ($from=='h5'){
  674. $post_data['trade_type'] = 'MWEB';
  675. }
  676. $result = $app->order->unify($post_data);
  677. if ($result['return_msg']=='OK'){
  678. if ($result['result_code']=='FAIL'){
  679. $com = false;
  680. Db::rollback();
  681. }else{
  682. $order1 = $app->jssdk->bridgeConfig($result['prepay_id']);//执行二次签名返回参数
  683. $retrun_data['order_no'] = $order_no;
  684. $retrun_data['id'] = $order['id'];
  685. $retrun_data['pay'] = json_decode($order1,true);
  686. Db::commit();
  687. }
  688. }else{
  689. $com = false;
  690. Db::rollback();
  691. }
  692. break;
  693. case 'zfb':
  694. $zfb = new AliPay();
  695. $notify_url = 'https://'.$_SERVER['HTTP_HOST'].'/api/Pay/alipaySecondaryNotify';//回调地址
  696. $order = $zfb->ali_pay_pc($body, $total_fee, $order_no, $notify_url,'https://'.$_SERVER['HTTP_HOST'].'/h5/pages/shop/order');//调用支付宝支付的方法
  697. $retrun_data['order_no'] = $order_no;
  698. $retrun_data['id'] = $order['id'];
  699. $retrun_data['pay'] = $order;
  700. Db::commit();
  701. break;
  702. case 'sd':
  703. $client = new Shande();
  704. $notify_url = 'https://'.$_SERVER['HTTP_HOST'].'/api/Pay/shandeSecondaryNotify';//回调地址
  705. $total_fee = $total_fee*100;
  706. $lenth = strlen($total_fee);
  707. $total_fee = get0number($lenth).$total_fee;
  708. $order_nos = get_order_sn();
  709. if (Db::name('store_order_info_order')
  710. ->where('order_no',$order_no)
  711. ->where('mid',$this->uid)
  712. ->update(['order_no'=>$order_nos])){
  713. $result = $client->orderPay($order_nos,$total_fee,$body,$notify_url,'https://'.$_SERVER['HTTP_HOST'].'/h5/pages/mine/mine',$user['bank_num']);
  714. $retrun_data['order_no'] = $order_nos;
  715. $retrun_data['id'] = $order['id'];
  716. $retrun_data['pay'] = json_decode($result['data'],true);
  717. if( $retrun_data['pay']['head']['respCode'] != '00000') throw new Exception($retrun_data['pay']['head']['respMsg'].'请重新下单');
  718. Db::commit();
  719. }else{
  720. $com=false;
  721. Db::rollback();
  722. }
  723. break;
  724. case 'wallet':
  725. if($user['money'] < $total_fee) throw new Exception('余额不足');
  726. $pay_res = (new Pay())->dealData(['out_trade_no' => $order_no,'attach'=>$this->uid]);
  727. if(!$pay_res) throw new Exception('支付失败');
  728. memberMoneyChange($total_fee,3,$this->uid,'二级市场余额支付',0,$order['id'],4);
  729. setMemberInfoHash($this->uid);
  730. Db::commit();
  731. break;
  732. }
  733. }catch (\Exception $e){
  734. $com=false;
  735. $error_msg= $e->getMessage();
  736. Db::rollback();
  737. }
  738. if ($com){
  739. $this->success('成功',$retrun_data);
  740. }
  741. $this->error($error_msg);
  742. }
  743. /**
  744. * @param 判断开关
  745. * @param string $pay_type
  746. * @return bool
  747. * @throws \think\db\exception\DataNotFoundException
  748. * @throws \think\db\exception\ModelNotFoundException
  749. * @throws \think\exception\DbException
  750. */
  751. public function checkSwitch($type,$pay_type=''){
  752. if ($type==1){
  753. $v = getConfigValue('secondary_sell_switch');
  754. if (!$v) $this->error('维护中,暂时关闭');
  755. }elseif ($type==2){
  756. $nameArray = ['secondary_wx_switch','secondary_zfb_switch','secondary_sd_switch'];
  757. $values = getConfig($nameArray);
  758. if ($pay_type=='wx'){
  759. if (!$values['secondary_wx_switch']) $this->error('微信支付暂时关闭');
  760. }elseif ($pay_type=='zfb'){
  761. if (!$values['secondary_zfb_switch']) $this->error('支付宝支付暂时关闭');
  762. }elseif ($pay_type=='sd'){
  763. if (!$values['secondary_sd_switch']) $this->error('杉德支付暂时关闭');
  764. }
  765. }
  766. return true;
  767. }
  768. }