Order.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. namespace app\controller\api;
  3. use app\extra\basic\Base;
  4. use app\extra\jhfPay\Pay;
  5. use app\extra\tools\CodeExtend;
  6. use app\middleware\WxMiddleware;
  7. use app\model\saas\SaasCart;
  8. use app\model\saas\SaasDiscount;
  9. use app\model\saas\SaasOrder;
  10. use app\model\saas\SaasOrderDetail;
  11. use app\model\saas\SaasPrintClient;
  12. use app\model\saas\SaasShop;
  13. use app\model\saas\SaasUser;
  14. use app\model\saas\SaasUserBuy;
  15. use app\model\saas\SaasUserLog;
  16. use LinFly\Annotation\Route\Controller;
  17. use LinFly\Annotation\Route\Middleware;
  18. use LinFly\Annotation\Route\Route;
  19. use support\Request;
  20. use support\Response;
  21. use think\facade\Db;
  22. #[Controller(prefix: "/wx_api/order"),Middleware(WxMiddleware::class)]
  23. class Order extends Base
  24. {
  25. protected array $noNeedLogin = [];
  26. protected array $types = [
  27. '1_1_1' => ['name' => '彩色-单面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  28. '1_1_2' => ['name' => '彩色-单面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  29. '1_2_1' => ['name' => '彩色-双面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  30. '2_1_1' => ['name' => '黑白-单面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  31. '2_2_1' => ['name' => '黑白-双面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  32. '2_1_2' => ['name' => '黑白-双面', 'amount' => 0, 'quantity' => 0,'discount' => 0],
  33. ];
  34. protected array $color = ["1" => "彩色", "2" => "黑白"];
  35. protected array $duplex = ["1" => "单面", "2" => "双面"];
  36. protected array $package = ["1" => "店内打印", "2" => '远程自取' , "3" => "商家配送"];
  37. #[Route(path: "list",methods: "get")]
  38. public function getOrderList(Request $request): Response
  39. {
  40. try {
  41. $param = $this->_valid([
  42. "page.require" => "参数错误",
  43. "size.require" => "参数错误",
  44. "type.require" => "参数错误",
  45. "shop.require" => "请选择店铺"
  46. ]);
  47. if (!is_array($param)) return error($param);
  48. $map = ["openid" => $request->user['openid'],"shop_id" => $param['shop']];
  49. $model = (new SaasOrder);
  50. if ($param['type'] > 0) {
  51. $map['status'] = $param['type'] - 1;
  52. } else {
  53. $model = $model->where("status",">",0);
  54. }
  55. $resp = $model->where($map)->append(["total"])->with(['shop' => function($query){
  56. $query->field('shop_id,shop_name');
  57. }])->withAttr(["total" => function($val,$resp){
  58. return (new SaasOrderDetail)->where("order_sn",$resp['order_sn'])->sum("number");
  59. }])->order("create_at desc")->paginate([
  60. "list_rows" => $param['size'],
  61. "page" => $param['page']
  62. ]);
  63. return success("ok",$resp->toArray());
  64. } catch (\Throwable $throwable) {
  65. return error($throwable->getMessage());
  66. }
  67. }
  68. /**
  69. * 订单详情
  70. * @param Request $request
  71. * @return Response
  72. */
  73. #[Route(path: "detail",methods: "get")]
  74. public function getOrderDetail(Request $request): Response
  75. {
  76. try {
  77. $param = $this->_valid([
  78. "order.require" => "参数错误"
  79. ]);
  80. if (!is_array($param)) return error($param);
  81. $resp = (new SaasOrder)->where("openid",$request->user['openid'])->where("order_sn",$param['order'])->append(["total","subscribe"])->with(['shop' => function($query){
  82. $query->field('shop_id,shop_name,shop_address');
  83. },"detail" => function($query){
  84. $query->field('order_sn,name,color,paper_size,duplex,number,page,extension,path,icon');
  85. }])->withAttr(["total" => function($val,$resp){
  86. return (new SaasOrderDetail)->where("order_sn",$resp['order_sn'])->sum("number");
  87. },"subscribe" => function(){
  88. return ["495E40hqOKoz5j_mWcf-UcmF6wkj_yIwCrTXicicH5w","UXJjDQ7NGstSwOxrKf_laGDmpID8Mm5MpXwFAd45d8U"];
  89. }])->findOrEmpty();
  90. if ($resp->isEmpty()) return error("订单数据错误");
  91. $resp['package_name'] = $this->package[$resp['package']];
  92. $resp['money'] = format_money($resp['money'] / 100);
  93. return success("ok",$resp->toArray());
  94. } catch (\Throwable $throwable) {
  95. return error($throwable->getMessage());
  96. }
  97. }
  98. /**
  99. * @param Request $request
  100. * @return Response
  101. */
  102. #[Route(path: "create",methods: "post")]
  103. public function createOrder(Request $request): Response
  104. {
  105. try {
  106. $param = $this->_valid([
  107. "shop.require" => trans("empty.require"),
  108. "print.require" => trans("empty.require"),
  109. "pay.require" => trans("empty.require"), // 1微信支付 2会员卡支付 3会员卡充值并支付
  110. "printName.default" => "",
  111. "express.require" => trans("empty.require"),
  112. "card.default" => "",
  113. "gift.default" => 0
  114. ],$request->method());
  115. if (!is_array($param)) return error($param);
  116. $cart = (new SaasCart)->where("shop_id",$param['shop'])->where("print_id",$param['print'])->where("openid",$request->user['openid'])->order("create_at desc")->select();
  117. if ($cart->isEmpty()) return error('请重新下单进行支付');
  118. $totalAmount = $totalDiscount = 0;
  119. foreach ($cart as $k=>$v){
  120. $key = $v['color'] . '_' . $v['duplex'] . '_' . $v['source'];
  121. if (isset($this->types[$key])) {
  122. $this->types[$key]['quantity'] += $v['page'];
  123. $this->types[$key]['amount'] += $v['money'];
  124. }
  125. $cart[$k] = $v;
  126. $cart[$k]['money'] = format_money($v['money'] / 100,2);
  127. $cart[$k]['name'] = msubstr($v['name'],0,12);
  128. }
  129. $printData = (new SaasPrintClient)->where("shop_id",$param['shop'])->where("code",$param['print'])->select();
  130. if ($printData->isEmpty()) return error('无可用打印机');
  131. // 计算折扣
  132. foreach ($this->types as $k=>$v) {
  133. $discount = (new SaasDiscount)->where("shop_id",$param['shop'])->where("keys",$k)->where("number",'<',$v['quantity'])->findOrEmpty();
  134. if (!$discount->isEmpty()) {
  135. $v['discount'] = round($v['amount'] * $discount['rate']);
  136. $this->types[$k]['discount'] = $v['discount'];
  137. }
  138. $totalAmount += $v['amount']; // 实际金额
  139. $totalDiscount += $v['discount']; // 折扣后金额
  140. }
  141. $orderSn = CodeExtend::uniqidDate(16).date("is").rand(1,9);
  142. $totalDay = (new SaasOrder)->where("shop_id",$param['shop'])->whereDay("create_at")->count();
  143. $orderData = [
  144. "shop_id" => $param['shop'], // 所属店铺
  145. "parent_id" => $param['shop'], // 消费店铺
  146. "openid" => $request->user['openid'],
  147. "order_sn" => $orderSn,
  148. "money" => $totalAmount,
  149. "discount" => $totalDiscount==0?$totalAmount:$totalDiscount, // 跟原价相等无折扣
  150. "print_name" => $param['printName'],
  151. "print_id" => $param['print'],
  152. "package" => $param['express'],
  153. "package_sn" => date('md')."-".sprintf("%02d",($totalDay+1)),
  154. "extra_money" => 0,
  155. "remark" => $param['remark']??''
  156. ];
  157. $shop = (new SaasShop)->where("shop_id",$param['shop'])->findOrEmpty();
  158. if ($param['pay'] == 2) { // 会员卡支付
  159. $card = (new SaasUser)->where("openid",$request->user['openid'])->where("shop_id",$param['shop'])->findOrEmpty();
  160. $payMoney = $totalDiscount > 0 ? $totalDiscount : $totalAmount;
  161. if ($payMoney >= $card['balance']) {
  162. return error("卡内余额不足~");
  163. }
  164. // 直接支付
  165. $card->balance = ($card['balance'] - $payMoney);
  166. $card->total_consume = ($card['total_consume'] + $payMoney);
  167. $card->save();
  168. $orderData['pay_type'] = 2;
  169. $orderData['status'] = 1;
  170. $orderData['pay_at'] = getDateFull();
  171. (new SaasOrder)->insertGetId($orderData);
  172. (new SaasUserLog)->insertGetId([
  173. "openid" => $request->user['openid'],
  174. "shop_id" => $param['shop'],
  175. "order_sn" => $orderSn,
  176. "money" => $payMoney,
  177. "card_no" => strtoupper(md5($request->user['openid'].$param['shop'])),
  178. "type" => 1,
  179. "balance" => $card['balance'] - $payMoney,
  180. ]);
  181. events("create-order",['shop' => $param['shop'],'print' => $param['print'],'openid' => $request->user['openid'],"order" => $orderSn]);
  182. return success("支付成功",['type' => 2,'data' => []]);
  183. }
  184. $options = [
  185. 'body' => "{$shop['shop_name']}-{$param['printName']}",
  186. 'out_trade_no' => $orderSn."-".$orderData['package_sn'],
  187. "attach" => $orderSn,
  188. 'total_fee' => $orderData['money'],
  189. 'openid' => $request->user['openid'],
  190. 'trade_type' => 'JSAPI',
  191. 'spbill_create_ip' => $request->getRealIp(),
  192. "notify_url" => "https://panel.huiyinduo.cn/notify/wx"
  193. ];
  194. if ($orderData['money'] <= 0) {
  195. return error("数据变动请重新上传再下单");
  196. }
  197. if ($param['pay'] == 3 && !empty($param['card'])) { // 开通会员卡并充值
  198. $buyCard = json_decode($param['card'],true);
  199. (new SaasUserBuy)->insertGetId([
  200. "shop_id" => $param['shop'],
  201. "money" => $buyCard['money'] * 100,
  202. "total_money" => ($buyCard['money'] * 100) + ($buyCard['old_money'] * 100),
  203. "order_sn" => $orderSn,
  204. "openid" => $request->user['openid'],
  205. "card_no" => strtoupper(md5($request->user['openid'].$param['shop']))
  206. ]);
  207. $options['body'] = $shop['shop_name']."-充值支付";
  208. $options['total_fee'] = $buyCard['money'] * 100;
  209. $options['notify_url'] = "https://panel.huiyinduo.cn/notify/recharge";
  210. }
  211. (new SaasOrder)->insertGetId($orderData);
  212. $param_data["order_no"] = $orderSn;
  213. $param_data["app_id"] = sConf("wechat.jhf_appid");
  214. $param_data["pay_channel"] = "wx_lite";
  215. $param_data["pay_amt"] = format_money($options['total_fee'] / 100 , 2);
  216. $param_data["goods_title"] = $options['body'];
  217. $param_data["device_info"] = array("device_ip" => $request->getRealIp());
  218. $param_data['notify_url'] = $options['notify_url'];
  219. $param_data["expend"] = [
  220. "wx_app_id" => sConf("wechat.mini_appid"),
  221. "open_id" => $request->user['openid']
  222. ];
  223. $respJhf = (new Pay)->config([
  224. "appid" => sConf("wechat.jhf_appid"),
  225. "mch_id" => sConf("wechat.jhf_mch_id"),
  226. "aeskey" => sConf("wechat.jhf_aeskey"),
  227. "pubkey" => sConf("wechat.jhf_pubkey"),
  228. "prikey" => sConf("wechat.jhf_prikey"),
  229. ])->createPay($param_data);
  230. // $wechat = new \WeChat\Pay($this->getWxConfig());
  231. // // 生成预支付码
  232. // echo getDateFull()."生成支付二维码\n";
  233. // print_r($options);
  234. // $result = $wechat->createOrder($options);
  235. if (isset($respJhf['code'])) {
  236. return error("发起支付失败");
  237. }
  238. // 创建JSAPI参数签名
  239. $resp = json_decode($respJhf['expend']['pay_info'],true);
  240. $resp['timestamp'] = $resp['timeStamp'];
  241. return success("ok",['type' => 1,"data" => $resp]);
  242. } catch (\Throwable $throwable) {
  243. echo $throwable->getLine()."\n";
  244. echo $throwable->getFile()."\n";
  245. return error($throwable->getMessage());
  246. }
  247. }
  248. /**
  249. * 小程序配置
  250. * @return array
  251. */
  252. protected function getWxConfig(): array
  253. {
  254. return [
  255. 'token' => 'test',
  256. 'appid' => sConf("wechat.mini_appid"),
  257. 'appsecret' => sConf("wechat.mini_secret"),
  258. 'encodingaeskey' => 'BJIUzE0gqlWy0GxfPp4J1oPTBmOrNDIGPNav1YFH5Z5',
  259. // 配置商户支付参数(可选,在使用支付功能时需要)
  260. 'mch_id' => sConf("wechat.mch_id"),
  261. 'mch_key' => sConf("wechat.mch_key")
  262. ];
  263. }
  264. }