Order.php 21 KB

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