GoodsOrder.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <?php
  2. namespace app\api\controller;
  3. use think\cache\driver\Redis;
  4. use think\Db;
  5. use think\Exception;
  6. use EasyWeChat\Factory;
  7. use think\Session;
  8. /**
  9. * @title 商品订单
  10. * @controller GoodsOrder
  11. * @group base
  12. */
  13. class GoodsOrder extends Base
  14. {
  15. public function initialize()
  16. {
  17. parent::initialize();
  18. parent::check_login();
  19. cancel_goods_order($this->uid);
  20. }
  21. /**
  22. * @title 生成订单(立即购买 )
  23. * @desc 生成订单(立即购买 )
  24. * @author qc
  25. * @url /api/Goods_order/createOrder
  26. * @method POST
  27. * @header name:Authorization require:1 desc:Token
  28. * @param name:goods_id type:int require:1 default:-- desc:商品id
  29. * @return name:order_id type:int require:0 default:0 desc:成功时返回订单id
  30. */
  31. public function createOrder()
  32. {
  33. // 验证会员是否3秒内提交过订单,3秒内提交过订单不再允许提交
  34. $redis = new Redis(['select'=>1]);
  35. if(!$redis->get('LOCK'.$this->uid)) {
  36. $redis->set('LOCK'.$this->uid,1,3);
  37. }else{
  38. $this->error('抢购中...');
  39. }
  40. $goods_id = input("post.goods_id");
  41. // 每秒最多允许 10笔订单通过
  42. $limit_cross = $redis->get('LIMITNUM'.$goods_id);
  43. if($limit_cross >=10){
  44. $this->error('服务器繁忙');
  45. }else if($limit_cross){
  46. $redis->inc('LIMITNUM'.$goods_id,1);
  47. }else{
  48. $redis->set('LIMITNUM'.$goods_id,1);
  49. }
  50. $num = input("post.num",1);
  51. $msg= ''; $com=true; $order_id = 0;
  52. Db::startTrans();
  53. try {
  54. $user_info = Db::name('store_member')->where('id',$this->uid)->find();
  55. if(!$user_info['is_auth']) throw new Exception('请实名认证后购买!');
  56. $goods_info = Db::table('store_goods')->where(['id'=>$goods_id,'type'=>1,'status'=>1,'is_deleted'=>0])->find();
  57. if(empty($goods_info)) throw new Exception('商品已下架,嘤嘤嘤~~~');
  58. if(strtotime($goods_info['sell_time']) > time()) throw new Exception('商品还未开始售卖!请耐心等待');
  59. if($goods_info['stock'] <= 0) throw new Exception('商品已售罄~~');
  60. if($goods_info['goods_price'] <= 0) throw new Exception('商品价格有误');
  61. $pro_info = [
  62. 'type'=>$goods_info['type'],
  63. 'is_gift'=>$goods_info['is_gift'],
  64. 'crystal'=>$goods_info['crystal'],
  65. 'gift_day'=>$goods_info['gift_day'],
  66. 'goods_price'=>$goods_info['goods_price'],
  67. ];
  68. $order_int =[
  69. 'uid' => $this->uid,
  70. 'order_no' => get_order_sn(),
  71. 'price_total' => $goods_info['goods_price'] * $num,
  72. 'goods_num' => $num,
  73. 'goods_id' => $goods_id,
  74. 'goods_cover' => $goods_info['cover'],
  75. 'goods_name' => $goods_info['name'],
  76. 'create_at' => date('Y-m-d H:i:s'),
  77. 'pro_info' => json_encode($pro_info),
  78. ];
  79. //扣减库存
  80. Db::table('store_goods')->where('id',$goods_id)->setDec('stock',$num);
  81. // 生成订单
  82. Db::table('goods_order')->insert($order_int);
  83. $order_id = Db::getLastInsID();
  84. Db::commit();
  85. }catch (\Exception $e){
  86. Db::rollback();
  87. $com=false;
  88. $msg = $e->getMessage();
  89. }
  90. if($com){
  91. $this->success('ok',['order_id'=>$order_id]);
  92. }else{
  93. $this->error($msg);
  94. }
  95. }
  96. /**
  97. * @title 获取订单详情
  98. * @desc 获取订单详情
  99. * @author qc
  100. * @url /api/Goods_order/getOrderDetail
  101. * @method GET
  102. * @header name:Authorization require:1 desc:Token
  103. * @param name:id type:int require:1 default:-- desc:订单id
  104. * @return name:order_no type:string default:-- desc:订单号
  105. * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),9取消
  106. * @return name:price_total type:float default:-- desc:订单金额
  107. * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
  108. * @return name:pay_no type:string default:-- desc:支付单号
  109. * @return name:create_at type:string default:-- desc:订单创建时间
  110. * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信)
  111. * @return name:pay_time type:string default:-- desc:支付时间
  112. * @return name:cancel_state type:int default:-- desc:取消状态
  113. * @return name:goods_id type:int default:-- desc:商品id
  114. * @return name:goods_num type:int default:-- desc:商品数量
  115. * @return name:goods_cover type:string default:-- desc:商品封面
  116. * @return name:goods_auth type:string default:-- desc:创作者
  117. * @return name:auth_img type:string default:-- desc:创作者头像
  118. * @return name:issuer type:string default:-- desc:发行方
  119. * @return name:detail type:string default:-- desc:详情
  120. * @return name:buy_notice type:string default:-- desc:购买须知
  121. * @return name:pay_content type:string default:-- desc:支付弹窗内容
  122. * @return name:pay_pic type:string default:-- desc:支付弹窗图片
  123. * @return name:adv_type type:int default:-- desc:广告类型(1图片,2mp3,3视频)
  124. * @return name:adv_cover type:string default:-- desc:广告图片
  125. * @return name:mp3_url type:string default:-- desc:广告mp3
  126. * @return name:audio_url type:string default:-- desc:广告视频
  127. */
  128. public function getOrderDetail()
  129. {
  130. $order_id = input('id',0);
  131. $detail = Db::table('goods_order')->alias('o')
  132. ->field('o.*,g.goods_auth,g.auth_img,g.goods_auth,g.issuer,g.detail,g.buy_notice,g.pay_content,g.pay_pic,g.type as goods_type,g.adv_type,g.adv_cover,g.mp3_url,g.audio_line,g.audio_url,g.vir_num')
  133. ->join('store_goods g','g.id = o.goods_id','LEFT')
  134. ->find($order_id);
  135. $this->success('获取成功',['detail'=>$detail]);
  136. }
  137. /**
  138. * @title 订单支付
  139. * @desc 订单支付
  140. * @author qc
  141. * @url /api/Goods_order/payOrder
  142. * @method POST
  143. * @header name:Authorization require:1 desc:Token
  144. * @param name:id type:int require:0 default:0 desc:订单id
  145. * @return name:config type:array default:0 desc:支付配置
  146. * @return name:config.appId type:string default:-- desc:公众账号ID
  147. * @return name:config.nonceStr type:string default:-- desc:随机字符串
  148. * @return name:config.signType type:string default:-- desc:签名类型
  149. * @return name:config.paySign type:string default:-- desc:签名
  150. * @return name:config.timestamp type:string default:-- desc:时间戳
  151. * @return name:goods_info type:array default:-- desc:商品
  152. * @return name:goods_info.pay_pic type:string default:-- desc:支付弹窗图片
  153. * @return name:goods_info.pay_content type:string default:-- desc:支付弹窗内容
  154. */
  155. public function payOrder(){
  156. Db::startTrans();
  157. $msg= 'ok';$config=false;
  158. try{
  159. $order_id = input('post.id',0);
  160. $order_info = Db::table('goods_order')->find($order_id);
  161. if(empty($order_info)) throw new Exception('订单不存在');
  162. if($order_info['status'] != 0 ) throw new Exception('订单状态有误!');
  163. $user_info = Db::table('store_member')->find($order_info['uid']);
  164. if(!$user_info['openid']) throw new Exception('用户openid为空!');
  165. $goods_info = Db::table('store_goods')->field('pay_pic,pay_content')->find($order_info['goods_id']);
  166. $pay_no = $order_info['pay_no'] ? $order_info['pay_no'] : get_order_sn();
  167. if(!$order_info['pay_no'])Db::table('goods_order')->where(['id'=>$order_id])->update(['pay_no'=>$pay_no]);
  168. $notify_url = $this->request->root(true) . '/api/Pay/goodsOrderNotify';
  169. // $order_info['price_total'] = 0.01;
  170. $config = Pay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'JSAPI',$user_info['openid']);
  171. $config ? Db::commit() :Db::rollback();
  172. }catch (\Exception $e){
  173. Db::rollback();
  174. $msg = $e->getMessage();
  175. }
  176. $config ? $this->success($msg,['config'=>$config,'goods_info'=>$goods_info]) : $this->error($msg);
  177. }
  178. /**
  179. * @title 取消订单
  180. * @desc 取消订单
  181. * @author qc
  182. * @url /api/Goods_order/cancelOrder
  183. * @method POST
  184. * @header name:Authorization require:1 desc:Token
  185. * @param name:id type:int require:1 default:-- desc:订单id
  186. */
  187. public function cancelOrder()
  188. {
  189. $is_commit = true;
  190. Db::startTrans();
  191. try {
  192. $order_id = input('post.id');
  193. $order_detail = Db::table('goods_order')->where(['id'=>$order_id,'uid'=>$this->uid])->find();
  194. if(empty($order_detail)) throw new Exception('订单不存在');
  195. if($order_detail['pay_state'] != 0) throw new Exception('订单已支付');
  196. if($order_detail['cancel_state'] != 0) throw new Exception('订单已取消,不能重复取消');
  197. //恢复库存
  198. Db::table('store_goods')->where('id',$order_detail['goods_id'])->setInc('stock',$order_detail['goods_num']);
  199. // 取消订单
  200. Db::table('goods_order')
  201. ->where(['id'=>$order_id])
  202. ->update(['cancel_state'=>1,'status'=>9]);
  203. Db::commit();
  204. }catch (\Exception $e){
  205. Db::rollback();
  206. $is_commit = false;
  207. $msg = $e->getMessage();
  208. }
  209. $is_commit ? $this->success('取消成功') : $this->error($msg);
  210. }
  211. /**
  212. * @title 获取订单列表
  213. * @desc 获取订单列表
  214. * @author qc
  215. * @url /api/Goods_order/getMyOrderList
  216. * @method GET
  217. * @header name:Authorization require:1 desc:Token
  218. * @param name:page type:int : default:1 desc:页数
  219. * @param name:page_num type:int : default:20 desc:每页数
  220. * @param name:status type:int : default:-1 desc:订单状态(-1全部,0待支付,1已支付(待发货),9取消)
  221. * @return name:order_no type:string default:-- desc:订单号
  222. * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),9取消
  223. * @return name:price_total type:float default:-- desc:订单金额
  224. * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
  225. * @return name:pay_no type:string default:-- desc:支付单号
  226. * @return name:create_at type:string default:-- desc:订单创建时间
  227. * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信)
  228. * @return name:pay_time type:string default:-- desc:支付时间
  229. * @return name:cancel_state type:int default:-- desc:取消状态
  230. * @return name:goods_id type:int default:-- desc:商品id
  231. * @return name:goods_num type:int default:-- desc:商品数量
  232. * @return name:goods_cover type:int default:-- desc:商品封面
  233. * @return name:past_int type:int default:-- desc:订单多少秒后过期
  234. * @return name:goods_name type:int default:-- desc:商品名称
  235. * @return name:goods_auth type:int default:-- desc:作者
  236. * @return name:pay_content type:string default:-- desc:支付弹窗内容
  237. * @return name:pay_pic type:string default:-- desc:支付弹窗图片
  238. */
  239. public function getMyOrderList()
  240. {
  241. $status = input('status',-1);
  242. $where=[];
  243. if($status > -1) $where['o.status'] = $status;
  244. $where['o.uid'] = $this->uid;
  245. $where['o.is_deleted'] = 0;
  246. $list = Db::table('goods_order')->alias('o')
  247. ->field('o.*,g.goods_auth,g.pay_content,g.pay_pic,g.vir_num')
  248. ->join('store_goods g','g.id = o.goods_id','LEFT')
  249. ->where($where)
  250. ->order('id desc')
  251. ->limit($this->off_set,$this->page_num)
  252. ->select();
  253. $set_time = intval(sysconf('cancel_time')) ? : 10;// 没设置默认5分钟未支付的自动取消
  254. array_walk($list,function (&$val) use ($set_time){
  255. $val['past_int'] = 0;
  256. if($val['status'] == 0 && strtotime($val['create_at']) + $set_time * 60 > time()){
  257. $val['past_int'] = strtotime($val['create_at']) + $set_time * 60 - time();
  258. }
  259. });
  260. $this->success('获取成功',['list'=>$list]);
  261. }
  262. /**
  263. * @title 删除订单
  264. * @desc 删除订单
  265. * @author qc
  266. * @url /api/Goods_order/delOrder
  267. * @method POST
  268. * @header name:Authorization require:1 desc:Token
  269. * @param name:id type:int require:1 default:1 desc:订单id
  270. */
  271. public function delOrder()
  272. {
  273. $order_id = input('post.id');
  274. $order_info = Db::table('goods_order')
  275. ->where(['uid'=>$this->uid,'is_deleted'=>0,'id'=>$order_id])
  276. ->find();
  277. if(empty($order_info)) $this->error('订单不存在');
  278. if($order_info['status'] == 0) $this->error('未取消订单不能删除');
  279. Db::table('goods_order')->where(['id'=>$order_id])->update(['is_deleted'=>1]);
  280. $this->success('删除成功');
  281. }
  282. }