OrderController.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controllers\User;
  4. use App\Controllers\BaseController;
  5. use App\Models\Invoice;
  6. use App\Models\Order;
  7. use App\Models\Product;
  8. use App\Models\UserCoupon;
  9. use App\Utils\Cookie;
  10. use App\Utils\Tools;
  11. use Exception;
  12. use Psr\Http\Message\ResponseInterface;
  13. use Slim\Http\Response;
  14. use Slim\Http\ServerRequest;
  15. use voku\helper\AntiXSS;
  16. use function explode;
  17. use function in_array;
  18. use function json_decode;
  19. use function json_encode;
  20. use function property_exists;
  21. use function time;
  22. final class OrderController extends BaseController
  23. {
  24. public static array $details = [
  25. 'field' => [
  26. 'op' => '操作',
  27. 'id' => '订单ID',
  28. 'product_id' => '商品ID',
  29. 'product_type' => '商品类型',
  30. 'product_name' => '商品名称',
  31. 'coupon' => '优惠码',
  32. 'price' => '金额',
  33. 'status' => '状态',
  34. 'create_time' => '创建时间',
  35. 'update_time' => '更新时间',
  36. ],
  37. ];
  38. /**
  39. * @throws Exception
  40. */
  41. public function order(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
  42. {
  43. return $response->write(
  44. $this->view()
  45. ->assign('details', self::$details)
  46. ->fetch('user/order/index.tpl')
  47. );
  48. }
  49. /**
  50. * @throws Exception
  51. */
  52. public function create(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
  53. {
  54. $antiXss = new AntiXSS();
  55. $product_id = $antiXss->xss_clean($request->getQueryParams()['product_id']) ?? null;
  56. $redir = Cookie::get('redir');
  57. if ($redir !== null) {
  58. Cookie::set(['redir' => ''], time() - 1);
  59. }
  60. if ($product_id === null || $product_id === '') {
  61. return $response->withRedirect('/user/product');
  62. }
  63. $product = Product::where('id', $product_id)->first();
  64. $product->content = json_decode($product->content);
  65. return $response->write(
  66. $this->view()
  67. ->assign('product', $product)
  68. ->fetch('user/order/create.tpl')
  69. );
  70. }
  71. /**
  72. * @throws Exception
  73. */
  74. public function detail(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
  75. {
  76. $antiXss = new AntiXSS();
  77. $id = $antiXss->xss_clean($args['id']);
  78. $order = Order::where('user_id', $this->user->id)->where('id', $id)->first();
  79. if ($order === null) {
  80. return $response->withRedirect('/user/order');
  81. }
  82. $order->product_type = $order->productType();
  83. $order->status = $order->status();
  84. $order->create_time = Tools::toDateTime($order->create_time);
  85. $order->update_time = Tools::toDateTime($order->update_time);
  86. $product_content = json_decode($order->product_content);
  87. $invoice = Invoice::where('order_id', $id)->first();
  88. $invoice->status = $invoice->status();
  89. $invoice->create_time = Tools::toDateTime($invoice->create_time);
  90. $invoice->update_time = Tools::toDateTime($invoice->update_time);
  91. $invoice->pay_time = Tools::toDateTime($invoice->pay_time);
  92. $invoice_content = json_decode($invoice->content);
  93. return $response->write(
  94. $this->view()
  95. ->assign('order', $order)
  96. ->assign('invoice', $invoice)
  97. ->assign('product_content', $product_content)
  98. ->assign('invoice_content', $invoice_content)
  99. ->fetch('user/order/view.tpl')
  100. );
  101. }
  102. public function process(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
  103. {
  104. $antiXss = new AntiXSS();
  105. $coupon_raw = $antiXss->xss_clean($request->getParam('coupon'));
  106. $product_id = $antiXss->xss_clean($request->getParam('product_id'));
  107. $product = Product::find($product_id);
  108. if ($product === null || $product->stock === 0) {
  109. return $response->withJson([
  110. 'ret' => 0,
  111. 'msg' => '商品无效',
  112. ]);
  113. }
  114. $buy_price = $product->price;
  115. $user = $this->user;
  116. if ($coupon_raw !== '') {
  117. $coupon = UserCoupon::where('code', $coupon_raw)->first();
  118. if ($coupon === null || ($coupon->expire_time !== 0 && $coupon->expire_time < time())) {
  119. return $response->withJson([
  120. 'ret' => 0,
  121. 'msg' => '优惠码无效',
  122. ]);
  123. }
  124. $coupon_limit = json_decode($coupon->limit);
  125. if ($coupon_limit->disabled) {
  126. return $response->withJson([
  127. 'ret' => 0,
  128. 'msg' => '优惠码无效',
  129. ]);
  130. }
  131. if ($coupon_limit->product_id !== '' && ! in_array($product_id, explode(',', $coupon_limit->product_id))) {
  132. return $response->withJson([
  133. 'ret' => 0,
  134. 'msg' => '优惠码无效',
  135. ]);
  136. }
  137. $coupon_use_limit = $coupon_limit->use_time;
  138. if ($coupon_use_limit > 0) {
  139. $user_use_count = Order::where('user_id', $user->id)->where('coupon', $coupon->code)->count();
  140. if ($user_use_count >= $coupon_use_limit) {
  141. return $response->withJson([
  142. 'ret' => 0,
  143. 'msg' => '优惠码无效',
  144. ]);
  145. }
  146. }
  147. if (property_exists($coupon_limit, 'total_use_time')) {
  148. $coupon_total_use_limit = $coupon_limit->total_use_time;
  149. } else {
  150. $coupon_total_use_limit = -1;
  151. }
  152. if ($coupon_total_use_limit > 0 && $coupon->use_count >= $coupon_total_use_limit) {
  153. return $response->withJson([
  154. 'ret' => 0,
  155. 'msg' => '优惠码无效',
  156. ]);
  157. }
  158. $content = json_decode($coupon->content);
  159. if ($content->type === 'percentage') {
  160. $discount = $product->price * $content->value / 100;
  161. } else {
  162. $discount = $content->value;
  163. }
  164. $buy_price = $product->price - $discount;
  165. }
  166. $product_limit = json_decode($product->limit);
  167. if ($product_limit->class_required !== '' && (int) $user->class < (int) $product_limit->class_required) {
  168. return $response->withJson([
  169. 'ret' => 0,
  170. 'msg' => '账户不满足购买条件',
  171. ]);
  172. }
  173. if ($product_limit->node_group_required !== ''
  174. && (int) $user->node_group !== (int) $product_limit->node_group_required) {
  175. return $response->withJson([
  176. 'ret' => 0,
  177. 'msg' => '账户不满足购买条件',
  178. ]);
  179. }
  180. if ($product_limit->new_user_required !== 0) {
  181. $order_count = Order::where('user_id', $user->id)->count();
  182. if ($order_count > 0) {
  183. return $response->withJson([
  184. 'ret' => 0,
  185. 'msg' => '账户不满足购买条件',
  186. ]);
  187. }
  188. }
  189. $order = new Order();
  190. $order->user_id = $user->id;
  191. $order->product_id = $product->id;
  192. $order->product_type = $product->type;
  193. $order->product_name = $product->name;
  194. $order->product_content = $product->content;
  195. $order->coupon = $coupon_raw;
  196. $order->price = $buy_price;
  197. $order->status = 'pending_payment';
  198. $order->create_time = time();
  199. $order->update_time = time();
  200. $order->save();
  201. $invoice_content = [];
  202. $invoice_content[] = [
  203. 'content_id' => 0,
  204. 'name' => $product->name,
  205. 'price' => $product->price,
  206. ];
  207. if ($coupon_raw !== '') {
  208. $invoice_content[] = [
  209. 'content_id' => 1,
  210. 'name' => '优惠码 ' . $coupon_raw,
  211. 'price' => '-' . $discount,
  212. ];
  213. }
  214. $invoice = new Invoice();
  215. $invoice->user_id = $user->id;
  216. $invoice->order_id = $order->id;
  217. $invoice->content = json_encode($invoice_content);
  218. $invoice->price = $buy_price;
  219. $invoice->status = 'unpaid';
  220. $invoice->create_time = time();
  221. $invoice->update_time = time();
  222. $invoice->pay_time = 0;
  223. $invoice->save();
  224. if ($product->stock > 0) {
  225. $product->stock -= 1;
  226. }
  227. $product->sale_count += 1;
  228. $product->save();
  229. if ($coupon_raw !== '') {
  230. $coupon->use_count += 1;
  231. $coupon->save();
  232. }
  233. return $response->withJson([
  234. 'ret' => 1,
  235. 'msg' => '成功创建订单,正在跳转账单页面',
  236. 'invoice_id' => $invoice->id,
  237. ]);
  238. }
  239. public function ajax(ServerRequest $request, Response $response, array $args): Response|ResponseInterface
  240. {
  241. $orders = Order::orderBy('id', 'desc')->where('user_id', $this->user->id)->get();
  242. foreach ($orders as $order) {
  243. $order->op = '<a class="btn btn-blue" href="/user/order/' . $order->id . '/view">查看</a>';
  244. if ($order->status === 'pending_payment') {
  245. $invoice_id = Invoice::where('order_id', $order->id)->first()->id;
  246. $order->op .= '
  247. <a class="btn btn-red" href="/user/invoice/' . $invoice_id . '/view">支付</a>';
  248. }
  249. $order->product_type = $order->productType();
  250. $order->status = $order->status();
  251. $order->create_time = Tools::toDateTime($order->create_time);
  252. $order->update_time = Tools::toDateTime($order->update_time);
  253. }
  254. return $response->withJson([
  255. 'orders' => $orders,
  256. ]);
  257. }
  258. }