Order.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\controller\merchant\store\behalfcustomerorder;
  12. use think\App;
  13. use think\facade\Cache;
  14. use crmeb\services\SmsService;
  15. use crmeb\basic\BaseController;
  16. use app\validate\api\UserAuthValidate;
  17. use app\validate\merchant\OrderValidate;
  18. use app\common\repositories\user\UserRepository;
  19. use app\common\repositories\store\order\StoreCartRepository;
  20. use app\common\repositories\store\order\StoreGroupOrderRepository;
  21. use app\common\repositories\store\order\MerchantOrderCreateRepository;
  22. class Order extends BaseController
  23. {
  24. protected $validate;
  25. protected $repository;
  26. protected $cartRepository;
  27. protected $userRepository;
  28. public function __construct(App $app, OrderValidate $validate, MerchantOrderCreateRepository $repository, StoreCartRepository $cartRepository, UserRepository $userRepository)
  29. {
  30. parent::__construct($app);
  31. $this->validate = $validate;
  32. $this->repository = $repository;
  33. $this->cartRepository = $cartRepository;
  34. $this->userRepository = $userRepository;
  35. }
  36. public function __destruct()
  37. {
  38. unset($this->validate);
  39. unset($this->repository);
  40. unset($this->cartRepository);
  41. unset($this->userRepository);
  42. }
  43. public function getValidate()
  44. {
  45. return $this->validate;
  46. }
  47. public function getRepository()
  48. {
  49. return $this->repository;
  50. }
  51. public function getCartRepository()
  52. {
  53. return $this->cartRepository;
  54. }
  55. public function getUserRepository()
  56. {
  57. return $this->userRepository;
  58. }
  59. /**
  60. * 检查订单
  61. *
  62. * @return void
  63. */
  64. public function check()
  65. {
  66. $params = $this->request->params(['uid', 'cart_ids', 'address_id', 'delivery_way', ['use_coupon', []], 'is_free_shipping', 'use_integral', 'tourist_unique_key']);
  67. $validate = $this->getValidate();
  68. if (!$validate->sceneCheck($params)) {
  69. return app('json')->fail($validate->getError());
  70. }
  71. $params['merId'] = $this->request->merId();
  72. if (!$this->isValidIntersection($params['cart_ids'], $params['uid'], $params['merId'], $params['tourist_unique_key'])) {
  73. return app('json')->fail('数据无效');
  74. }
  75. return app('json')->success('ok', $this->getRepository()->checkOrder($params));
  76. }
  77. /**
  78. * 创建订单
  79. *
  80. * @return void
  81. */
  82. public function create()
  83. {
  84. $params = $this->request->params(
  85. [
  86. 'uid', // 用户ID
  87. 'cart_ids', // 购物车ID集合,数组类型
  88. 'address_id', // 地址ID
  89. 'delivery_way', // 配送方式
  90. ['use_coupon', []], // 使用的优惠券ID集合,数组类型
  91. 'is_free_shipping', // 是否免运费
  92. 'use_integral', // 是否使用积分
  93. 'tourist_unique_key', // 游客唯一标识
  94. 'pay_type', // 支付方式
  95. 'key', // 订单key
  96. 'mark', // 备注
  97. 'old_pay_price' // 原支付价格
  98. ]
  99. );
  100. $params['merId'] = $this->request->merId();
  101. $merchant = $this->getRepository()->merchantInfo($params['merId']);
  102. // 验证参数
  103. $validate = $this->getValidate();
  104. if (!$validate->sceneCreate($params, $merchant)) {
  105. return app('json')->fail($validate->getError());
  106. }
  107. $params['pay_type'] = ($params['pay_type'] === 'pc') ? 'balance' : $params['pay_type'];
  108. if (!in_array($params['pay_type'], MerchantOrderCreateRepository::PAY_TYPE, true)) {
  109. return app('json')->fail('请选择正确的支付方式');
  110. }
  111. // 幂等验证,防止重复提交订单
  112. if (!$this->isValidIntersection($params['cart_ids'], $params['uid'], $params['merId'], $params['tourist_unique_key'])) {
  113. return app('json')->fail('已生成订单,请勿重复提交~');
  114. }
  115. // 创建订单
  116. $repository = $this->getRepository();
  117. $groupOrder = $repository->createOrder($params);
  118. if (!$groupOrder) {
  119. return app('json')->fail('创建订单失败');
  120. }
  121. $data = ['order_id' => $groupOrder->group_order_id, 'pay_type' => $params['pay_type'], 'pay_price' => $groupOrder['pay_price']];
  122. // 金额为0,直接设置为已付款,并返回支付成功信息
  123. if ($groupOrder['pay_price'] == 0) {
  124. $repository->paySuccess($groupOrder);
  125. return app('json')->success('支付成功', $data);
  126. }
  127. // 线下支付,直接返回成功
  128. if ($params['pay_type'] == 'offline') {
  129. return app('json')->success('线下支付,请确认', $data);
  130. }
  131. return app('json')->success('创建订单成功', $data);
  132. }
  133. /**
  134. * 获取支付方式列表,支付方式配置信息等
  135. *
  136. * @return void
  137. */
  138. public function payConfig()
  139. {
  140. $params = $this->request->params(['uid']);
  141. $validate = $this->getValidate();
  142. if (!$validate->scenePayConfig($params)) {
  143. return app('json')->fail($validate->getError());
  144. }
  145. $uid = $params['uid'];
  146. $config = $this->repository->merchantPayConfig($uid, $this->request->merId());
  147. if (!$config) {
  148. return app('json')->fail('获取支付配置失败');
  149. }
  150. $config['yue_pay_status'] = $uid ? $config['yue_pay_status'] : 0;
  151. return app('json')->success($config);
  152. }
  153. /**
  154. * 订单付款操作
  155. *
  156. * @param [type] $id
  157. * @return json
  158. */
  159. public function pay($id, StoreGroupOrderRepository $groupOrderRepository)
  160. {
  161. $params = $this->request->params(['uid', 'pay_type', 'phone', 'sms_code', 'auth_code']);
  162. $params['id'] = $id;
  163. $validate = $this->getValidate();
  164. $groupOrder = $groupOrderRepository->detail($params['uid'], $id, false);
  165. if (!$validate->scenePay($params, $groupOrder)) {
  166. return app('json')->fail($validate->getError());
  167. }
  168. $repository = $this->getRepository();
  169. $payType = $params['pay_type'];
  170. if ($payType == 'balance') {
  171. $smsCode = app()->make(SmsService::class)->checkSmsCode($params['phone'], $params['sms_code'], 'balance');
  172. if (!$smsCode) {
  173. return app('json')->fail('验证码不正确');
  174. }
  175. }
  176. $repository->changePayType($groupOrder, array_search($payType, MerchantOrderCreateRepository::PAY_TYPE));
  177. // 金额为0,直接设置为已付款
  178. if ($groupOrder['pay_price'] == 0) {
  179. $repository->paySuccess($groupOrder);
  180. return app('json')->success('支付成功', ['order_id' => $groupOrder['group_order_id']]);
  181. }
  182. // 线下支付,直接返回成功
  183. if ($payType == 'offline') {
  184. return app('json')->success('线下支付,请确认', ['order_id' => $groupOrder['group_order_id']]);
  185. }
  186. $user = $this->getUserRepository()->userInfo($params['uid']);
  187. // 支付操作
  188. try {
  189. return $repository->merchantPay($params, $user, $groupOrder);
  190. } catch (\Exception $e) {
  191. return app('json')->fail('支付失败', $e->getMessage(), ['order_id' => $groupOrder->group_order_id, 'pay_price' => $groupOrder->pay_price]);
  192. }
  193. }
  194. /**
  195. * 获取支付状态
  196. *
  197. * @param $id
  198. * @return void
  199. */
  200. public function payStatus($id)
  201. {
  202. $params = $this->request->params(['uid', 'pay_type']);
  203. $params['id'] = $id;
  204. $validate = $this->getValidate();
  205. if (!$validate->sceneStatus($params)) {
  206. return app('json')->fail($validate->getError());
  207. }
  208. $orderRepository = $this->getRepository();
  209. $status = $orderRepository->payStatus($params);
  210. return app('json')->success($status);
  211. }
  212. /**
  213. * 余额支付获取验证码
  214. *
  215. * @param UserAuthValidate $validate
  216. * @return void
  217. */
  218. public function verify(UserAuthValidate $validate)
  219. {
  220. $data = $this->request->params(['phone', ['type', 'balance']]);
  221. $validate->sceneVerify()->check($data);
  222. $smsLimitKey = 'sms_limit_' . $data['phone'];
  223. $limit = Cache::get($smsLimitKey) ?? 0;
  224. $smsLimit = systemConfig('smsLimit');
  225. if ($smsLimit && $limit > $smsLimit) {
  226. return app('json')->fail('请求太频繁请稍后再试');
  227. }
  228. try {
  229. $smsCode = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);
  230. $smsTime = systemConfig('sms_time') ?? 30;
  231. SmsService::create()->send($data['phone'], 'VERIFICATION_CODE', ['code' => $smsCode, 'time' => $smsTime]);
  232. } catch (\Exception $e) {
  233. return app('json')->fail($e->getMessage());
  234. }
  235. $smsKey = app()->make(SmsService::class)->sendSmsKey($data['phone'], $data['type']);
  236. Cache::set($smsKey, $smsCode, $smsTime * 60);
  237. Cache::set($smsLimitKey, $limit + 1, 60);
  238. // 短信发送成功
  239. return app('json')->success('短信发送成功');
  240. }
  241. private function isValidIntersection(array $cartIds, int $uid, int $merId, string $touristUniqueKey)
  242. {
  243. return (count($cartIds) == count($this->getCartRepository()->validIntersection($cartIds, $uid, $merId, $touristUniqueKey)));
  244. }
  245. }