Order.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\library\AliPay;
  4. use think\cache\driver\Redis;
  5. use think\Db;
  6. use think\Exception;
  7. use EasyWeChat\Factory;
  8. use think\Session;
  9. use function Sodium\add;
  10. /**
  11. * @title 订单
  12. * @controller GoodsOrder
  13. * @group base
  14. */
  15. class Order extends Base
  16. {
  17. public function initialize()
  18. {
  19. parent::initialize();
  20. parent::check_login();
  21. }
  22. /**
  23. * @title 生成订单(立即购买 )
  24. * @desc 生成订单(立即购买 )
  25. * @author Gavin
  26. * @url /api/Order/createOrder
  27. * @method POST
  28. * @header name:Authorization require:1 desc:Token
  29. * @param name:id type:int require:1 default:-- desc:藏品id
  30. * @param name:num type:int require:1 default:1 desc:数量
  31. * @param name:pay_type type:string require:1 default:wx desc:wx:微信zfb:支付宝
  32. * @param name:from type:string require:1 default:wx desc:wx:微信公众号h5:网页
  33. *
  34. * @return name:order_no type:int require:0 default:0 desc:订单号
  35. * @return name:pay type:string require:0 default:0 desc:支付信息
  36. */
  37. public function createOrder()
  38. {
  39. $id = input('id');
  40. $num = input('num',1);
  41. $pay_type = input('pay_type','wx');
  42. $from = input('from','wx');
  43. if (!$id || !$num) $this->error('参数错误');
  44. $user = getMemberInfoHash($this->uid); //获取用户信息
  45. if ($user['is_auth']==0) $this->error('请实名认证后购买!');
  46. $coll_info = getCollectionInfoHash($id);
  47. if ($coll_info['is_deleted']==1 || $coll_info['status']==0) $this->error('藏品已下架');
  48. $inventory = getCollectionInventory($id);
  49. if ($inventory<1) $this->error('已售罄');
  50. $sell_time = strtotime($coll_info['sell_time']);
  51. if ($sell_time>time()) $this->error('商品还未开始售卖!请耐心等待');
  52. //获取用户已经购买数量
  53. $userByCount = getByCount($this->uid,$id);
  54. if ($coll_info['buy_count']<($userByCount+$num)) $this->error('每人限购'.$coll_info['buy_count'].'个');
  55. //获取是否已经铸造hash
  56. $hashCount = getLenCollection($id);
  57. if (!$hashCount || $hashCount<$num) $this->error('hash未铸造,无法购买');
  58. if ($from=='wx'){
  59. if (!$user['openid']) $this->error('微信未授权,无法购买');
  60. }
  61. //先减掉库存
  62. loseCollectionInventory($id,$num);
  63. //先增加购买数量
  64. IncrByCount($this->uid,$id,$num);
  65. $order_no = get_order_sn();
  66. $total_fee = bcmul($coll_info['price'],$num,2);
  67. $redis_data = [
  68. 'mid'=>$this->uid,
  69. 'c_id'=>$id,
  70. 'order_no'=>$order_no,
  71. 'inventory'=>$coll_info['inventory'],
  72. 'num'=>$num,
  73. 'pro_info'=>json_encode($coll_info),
  74. 'status'=>0,
  75. 'create_at'=>date('Y-m-d H:i:s'),
  76. 'pay_price'=>$total_fee,
  77. 'pay_type'=>$pay_type
  78. ];
  79. $com = true;
  80. $body = '纪元部落购买藏品';
  81. switch ($pay_type){
  82. case 'wx':
  83. $config = retrunWxConfig();
  84. $total_fee = $total_fee * 100;
  85. $config['notify_url'] = $this->request->root(true).'/api/Pay/WxOrderNotify';
  86. $app = Factory::payment($config);
  87. $post_data = [
  88. 'body' => $body,
  89. 'out_trade_no' => $order_no,
  90. 'total_fee' => $total_fee,
  91. 'attach'=>$this->uid, //自定义传值
  92. ];
  93. //trade_type SAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
  94. if ($from=='wx'){
  95. $post_data['openid'] = $user['openid'];
  96. $post_data['trade_type'] = 'JSAPI';
  97. }elseif ($from=='h5'){
  98. $post_data['trade_type'] = 'MWEB';
  99. }
  100. $result = $app->order->unify($post_data);
  101. if ($result['return_msg']=='OK'){
  102. if ($result['result_code']=='FAIL'){
  103. $com = false;
  104. }else{
  105. $order1 = $app->jssdk->bridgeConfig($result['prepay_id']);//执行二次签名返回参数
  106. $redis_data['wx_order'] = $order1;
  107. $retrun_data['order_no'] = $order_no;
  108. $retrun_data['pay'] = json_decode($order1,true);
  109. }
  110. }else{
  111. $com = false;
  112. }
  113. break;
  114. case 'zfb':
  115. $zfb = new AliPay();
  116. $notify_url = $this->request->root(true).'/api/Pay/alipayOrderNotify?uid='.$this->uid;//回调地址
  117. $order = $zfb->aliPay($body, $total_fee, $order_no, $notify_url);//调用支付宝支付的方法
  118. $retrun_data['order_no'] = $order_no;
  119. $retrun_data['pay'] = $order;
  120. break;
  121. }
  122. // $retrun_data['order_no'] = $order_no;
  123. // $retrun_data['pay'] = '';
  124. if ($com){
  125. $redis = new Redis();
  126. //收集下单用户id
  127. setCollectionBuyUser($this->uid);
  128. $redis->hMSet('order_not_pay_'.$this->uid,[$order_no=>json_encode($redis_data)]); //存入redis
  129. $this->success('成功',$retrun_data);
  130. }else{
  131. //加上库存
  132. addCollectionInventory($id,$num);
  133. //减少用户购买数量
  134. DecrByCount($this->uid,$id,$num);
  135. $this->error('服务器繁忙,请稍后重试');
  136. }
  137. }
  138. /**
  139. * @title 我的订单-待支付、已购买
  140. * @desc 我的订单-待支付、已购买
  141. * @author Gavin
  142. * @url /api/Order/getMyOrderList
  143. * @method POST
  144. * @header name:Authorization require:1 desc:Token
  145. * @param name:status type:int : default:0 desc:0:待支付1:已购买
  146. * @param name:page type:int : default:1 desc:页数
  147. * @param name:page_num type:int : default:20 desc:每页数
  148. *
  149. * @return name:order_no type:string default:-- desc:订单号
  150. * @return name:num type:int default:-- desc:数量
  151. * @return name:pay_price type:string default:-- desc:订单金额
  152. * @return name:status type:int default:-- desc:类型0:待支付1:已支付
  153. * @return name:cancel_time type:string default:-- desc:待支付自动取消时间
  154. * @return name:pay_type type:string default:-- desc:支付方式wx:微信zfb:支付宝
  155. * @return name:create_at type:string default:-- desc:创建时间
  156. * @return name:pro_info@name type:string default:-- desc:藏品名称
  157. * @return name:pro_info@cover type:string default:-- desc:藏品图片
  158. * @return name:pro_info@price type:string default:-- desc:藏品单价
  159. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  160. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  161. */
  162. public function getMyOrderList(){
  163. $status = input('status',0);
  164. if ($status==0){
  165. $redis = new Redis();
  166. $key = 'order_not_pay_'.$this->uid;
  167. $count = $redis->hGetLen($key);
  168. $list = $redis->hGetvals($key);
  169. if ($list){
  170. //自动取消分钟数
  171. $cancel_time = getCancelTime();
  172. foreach ($list as $k=>&$v){
  173. $info = json_decode($v,true);
  174. $info['pro_info'] = json_decode($info['pro_info'],true);
  175. $info['cancel_time'] = date('Y-m-d H:i:s',strtotime($info['create_at'])+($cancel_time*60));
  176. $list[$k] = $info;
  177. }
  178. }
  179. }else{
  180. $where = [
  181. 'is_deleted'=>0,
  182. 'status'=>$status,
  183. 'mid'=>$this->uid
  184. ];
  185. $count = Db::name('store_order')->where($where)->count();
  186. $list = Db::name('store_order')
  187. ->where($where)
  188. ->field('id,c_id,order_no,num,pro_info,status,create_at,pay_price,pay_type')
  189. ->order('id desc')
  190. ->limit($this->off_set,$this->page_num)
  191. ->select();
  192. foreach ($list as &$v){
  193. $v['pro_info'] = json_decode($v['pro_info'],true);
  194. }
  195. }
  196. $this->success('成功',compact('count','list'));
  197. }
  198. /**
  199. * @title 待支付、已购买订单详情
  200. * @desc 待支付、已购买订单详情
  201. * @author Gavin
  202. * @url /api/Order/MyOrderListDetail
  203. * @method POST
  204. * @header name:Authorization require:1 desc:Token
  205. * @param name:order_no type:string default:0 desc:订单号
  206. * @param name:type type:int default:1 desc:1:待支付2:已支付
  207. *
  208. * @return name:order_no type:string default:-- desc:订单号
  209. * @return name:num type:int default:-- desc:数量
  210. * @return name:pay_price type:string default:-- desc:订单金额
  211. * @return name:status type:int default:-- desc:类型0:待支付1:已支付
  212. * @return name:cancel_time type:string default:-- desc:待支付自动取消时间
  213. * @return name:create_at type:string default:-- desc:创建时间
  214. * @return name:pay_at type:string default:-- desc:支付时间
  215. * @return name:pay_type type:string default:-- desc:支付方式wx:微信zfb:支付宝
  216. * @return name:pro_info@name type:string default:-- desc:藏品名称
  217. * @return name:pro_info@cover type:string default:-- desc:藏品图片
  218. * @return name:pro_info@price type:string default:-- desc:藏品单价
  219. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  220. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  221. */
  222. public function MyOrderListDetail(){
  223. $order_no = input('order_no');
  224. $type = input('type',1);
  225. if (!$order_no) $this->error('参数错误');
  226. if ($type==1){
  227. $redis = new Redis();
  228. $key = 'order_not_pay_'.$this->uid;
  229. $order = $redis->hGet($key,$order_no);
  230. $order = json_decode($order,true);
  231. }else{
  232. $order = Db::name('store_order')
  233. ->where('order_no',$order_no)
  234. ->where('mid',$this->uid)
  235. ->where('is_deleted',0)
  236. ->find();
  237. }
  238. if (!$order) $this->error('订单不存在');
  239. $order['pro_info'] = json_decode($order['pro_info'],true);
  240. //自动取消分钟数
  241. $cancel_time = getCancelTime();
  242. if ($order['status']==0){
  243. $order['cancel_time'] = date('Y-m-d H:i:s',strtotime($order['create_at'])+($cancel_time*60));
  244. }
  245. $this->success('成功',$order);
  246. }
  247. /**
  248. * @title 待支付订单支付
  249. * @desc 待支付订单支付
  250. * @author Gavin
  251. * @url /api/Order/payOrder
  252. * @method POST
  253. * @header name:Authorization require:1 desc:Token
  254. * @param name:order_no type:string require:1 default:-- desc:订单号
  255. * @param name:from type:string require:1 default:wx desc:wx:微信公众号h5:网页
  256. *
  257. * @return name:order_no type:int require:0 default:0 desc:订单号
  258. * @return name:pay type:string require:0 default:0 desc:支付信息
  259. */
  260. public function payOrder(){
  261. $user = getMemberInfoHash($this->uid); //获取用户信息
  262. $order_no = input('order_no'); //订单号
  263. $from = input('from','wx');
  264. if (!$order_no) $this->error('参数错误');
  265. $redis = new Redis();
  266. $key = 'order_not_pay_'.$this->uid;
  267. $order = $redis->hGet($key,$order_no);
  268. if (!$order) $this->error('订单不存在');
  269. $order = json_decode($order,true);
  270. if ($order['status']!=0) $this->error('订单已支付或已取消');
  271. $order_no = $order['order_no'];
  272. $total_fee = $order['pay_price'];
  273. $pay_type = $order['pay_type'];
  274. $body = '纪元部落购买藏品';
  275. $com = true;
  276. switch ($pay_type){
  277. case 'wx':
  278. $config = retrunWxConfig();
  279. $total_fee = $total_fee * 100;
  280. $config['notify_url'] = $this->request->root(true).'/api/Pay/WxOrderNotify';
  281. $app = Factory::payment($config);
  282. $post_data = [
  283. 'body' => $body,
  284. 'out_trade_no' => $order_no,
  285. 'total_fee' => $total_fee,
  286. 'attach'=>$this->uid, //自定义传值
  287. ];
  288. //trade_type SAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
  289. if ($from=='wx'){
  290. $post_data['openid'] = $user['openid'];
  291. $post_data['trade_type'] = 'JSAPI';
  292. }elseif ($from=='h5'){
  293. $post_data['trade_type'] = 'MWEB';
  294. }
  295. $result = $app->order->unify($post_data);
  296. if ($result['return_msg']=='OK'){
  297. if ($result['result_code']=='FAIL'){
  298. $com = false;
  299. }else{
  300. $order1 = $app->jssdk->bridgeConfig($result['prepay_id']);//执行二次签名返回参数
  301. $redis_data['wx_order'] = $order1;
  302. $retrun_data['order_no'] = $order_no;
  303. $retrun_data['pay'] = json_decode($order1,true);
  304. }
  305. }else{
  306. $com = false;
  307. }
  308. break;
  309. case 'zfb':
  310. $zfb = new AliPay();
  311. $notify_url = $this->request->root(true).'/api/Pay/alipayOrderNotify?uid='.$this->uid;//回调地址
  312. $order = $zfb->aliPay($body, $total_fee, $order_no, $notify_url);//调用支付宝支付的方法
  313. $retrun_data['order_no'] = $order_no;
  314. $retrun_data['pay'] = $order;
  315. break;
  316. }
  317. if ($com){
  318. $this->success('成功',$retrun_data);
  319. }else{
  320. $this->error('调起支付失败,请稍后重试');
  321. }
  322. }
  323. /**
  324. * @title 取消订单
  325. * @desc 取消订单
  326. * @author Gavin
  327. * @url /api/Order/cancelOrder
  328. * @method POST
  329. * @header name:Authorization require:1 desc:Token
  330. * @param name:order_no type:string require:1 default:-- desc:订单号
  331. */
  332. public function cancelOrder(){
  333. $order_no = input('order_no');
  334. if (!$order_no) $this->error('参数错误');
  335. $redis = new Redis();
  336. $key = 'order_not_pay_'.$this->uid;
  337. $order = $redis->hGet($key,$order_no);
  338. if (!$order) $this->error('订单不存在');
  339. $order = json_decode($order,true);
  340. if ($order['status']!=0) $this->error('订单已支付或已取消');
  341. $com = true;
  342. Db::startTrans();
  343. try {
  344. $order['status'] = 2;
  345. $order['cancel_at'] = date('Y-m-d H:i:s');
  346. $order['cancel_state'] = 2;
  347. Db::name('store_order')->insert($order);
  348. Db::commit();
  349. }catch (\Exception $e){
  350. $com=false;
  351. Db::rollback();
  352. }
  353. if ($com){
  354. //加上库存
  355. addCollectionInventory($order['c_id'],$order['num']);
  356. //减少用户购买数量
  357. DecrByCount($this->uid,$order['c_id'],$order['num']);
  358. //删除数据
  359. $redis->hdel($key,$order_no);
  360. $this->success('取消成功');
  361. }else{
  362. $this->error('取消失败,请稍后重试');
  363. }
  364. }
  365. /**
  366. * @title 我的订单-转赠
  367. * @desc 我的订单-转赠
  368. * @author Gavin
  369. * @url /api/Order/getMySendList
  370. * @method POST
  371. * @header name:Authorization require:1 desc:Token
  372. * @param name:page type:int : default:1 desc:页数
  373. * @param name:page_num type:int : default:20 desc:每页数
  374. *
  375. * @return name:order_no type:string default:-- desc:订单号
  376. * @return name:over_time type:string default:-- desc:转赠时间
  377. * @return name:status type:int default:-- desc:类型2:赠出3:获赠
  378. * @return name:send_name type:string default:-- desc:转赠者/受赠者
  379. * @return name:collectors_hash type:string default:-- desc:hash
  380. * @return name:pro_info@name type:string default:-- desc:藏品名称
  381. * @return name:pro_info@price type:string default:-- desc:藏品价格
  382. * @return name:pro_info@price type:string default:-- desc:藏品单价
  383. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  384. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  385. */
  386. public function getMySendList(){
  387. $where = [
  388. 'mid'=>$this->uid,
  389. ];
  390. $count = Db::name('store_order_info')->where($where)->whereIn('status','2,3')->count();
  391. $list = Db::name('store_order_info')
  392. ->where($where)
  393. ->whereIn('status','2,3')
  394. ->field('id,order_no,pro_info,over_time,create_at,status,to_mid,collectors_hash')
  395. ->order('id desc')
  396. ->limit($this->off_set,$this->page_num)
  397. ->select();
  398. foreach ($list as &$v){
  399. $v['pro_info'] = json_decode($v['pro_info'],true);
  400. $v['send_name'] = Db::name('store_member')->where('id',$v['to_mid'])->value('name');
  401. }
  402. $this->success('成功',compact('count','list'));
  403. }
  404. /**
  405. * @title 转赠订单详情
  406. * @desc 转赠订单详情
  407. * @author Gavin
  408. * @url /api/Order/getMySendListDetail
  409. * @method POST
  410. * @header name:Authorization require:1 desc:Token
  411. * @param name:order_id type:int : default:1 desc:订单ID
  412. *
  413. * @return name:order_no type:string default:-- desc:订单号
  414. * @return name:over_time type:string default:-- desc:转赠时间
  415. * @return name:status type:int default:-- desc:类型2:赠出3:获赠
  416. * @return name:send_name type:string default:-- desc:转赠者/受赠者
  417. * @return name:collectors_hash type:string default:-- desc:hash
  418. * @return name:pro_info@name type:string default:-- desc:藏品名称
  419. * @return name:pro_info@price type:string default:-- desc:藏品价格
  420. * @return name:pro_info@price type:string default:-- desc:藏品单价
  421. * @return name:pro_info@auth_img type:string default:-- desc:藏品作者头像
  422. * @return name:pro_info@auth_name type:string default:-- desc:藏品作者名称
  423. */
  424. public function getMySendListDetail(){
  425. $order_id = input('order_id'); //订单id
  426. if (!$order_id) $this->error('参数错误');
  427. $order = Db::name('store_order_info')
  428. ->where('id',$order_id)
  429. ->where('mid',$this->uid)
  430. ->find();
  431. if (!$order) $this->error('订单不存在');
  432. $order['pro_info'] = json_decode($order['pro_info'],true);
  433. $order['send_name'] = Db::name('store_member')->where('id',$order['to_mid'])->value('name');
  434. $this->success('成功',$order);
  435. }
  436. function savetest($order_no){
  437. $result['out_trade_no'] = $order_no;
  438. $order = Db::name('store_order')->where('order_no',$result['out_trade_no'])->find();
  439. if ($order['status']==0){
  440. Db::startTrans();
  441. try {
  442. Db::name('store_order')
  443. ->where('order_no',$result['out_trade_no'])
  444. ->update(['status'=>1,'pay_at'=>date('Y-m-d H:i:s'),'return_success_info'=>json_encode($result,true)]);
  445. $array = [];
  446. for ($i=0;$i<$order['num'];$i++){
  447. //获取排名
  448. $rank = getRanking($order['c_id'])+1;
  449. $tag = getTag($order['c_id'],$rank,$order['inventory']);
  450. saveRanking($order['c_id']);
  451. $company = '象寻数字科技(上海)有限公司';
  452. $company_hash = '';
  453. $company_hash_time = '';
  454. $collectors_hash = '';
  455. $date = [
  456. 'order_id'=>$order['id'],
  457. 'order_no'=>get_order_sn(),
  458. 'tag'=>$tag,
  459. 'mid'=>$order['mid'],
  460. 'pro_info'=>$order['pro_info'],
  461. 'company'=>$company,
  462. 'company_hash'=>$company_hash,
  463. 'company_hash_time'=>$company_hash_time,
  464. 'collectors_hash'=>$collectors_hash,
  465. 'collectors_hash_time'=>date('Y-m-d H:i:s')
  466. ];
  467. $array[] = $date;
  468. }
  469. Db::name('store_order_info')->insertAll($array);
  470. Db::commit();
  471. // return true;
  472. } catch (\Exception $e){
  473. Db::rollback();
  474. //return false;
  475. }
  476. }
  477. }
  478. }