OrderPayDataForm.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\alliance\models\order;
  8. use app\models\AccountLog;
  9. use app\models\common\CommonOrder;
  10. use app\models\Goods;
  11. use app\models\GoodsBook;
  12. use app\models\Order;
  13. use app\models\OrderDetail;
  14. use app\models\OrderUnion;
  15. use app\models\SaasUser;
  16. use app\models\Store;
  17. use app\models\User;
  18. use app\models\VerifyCardLog;
  19. use app\models\VerifyCardSale;
  20. use app\modules\alliance\models\AllianceOrderComplete;
  21. use app\modules\client\models\v1\LoginForm;
  22. use app\modules\client\models\v1\ShareMoneyForm;
  23. use app\utils\Alipay\Alipay;
  24. use app\utils\Alipay\AlipayProfit;
  25. use app\utils\Alipay\AlipayUnion;
  26. use app\utils\CloudPrint;
  27. use app\utils\OrderNo;
  28. use app\utils\Share\BonusPool;
  29. use app\utils\Wechat\WechatNewPay;
  30. use app\utils\Wechat\WechatPay;
  31. use app\utils\Wechat\WechatAlliancePay;
  32. use app\utils\yunst\src\OrderYunst;
  33. use ByteDance\ByteDance;
  34. use yii\base\Model;
  35. use yii\helpers\Json;
  36. use app\utils\Delivery\Delivery;
  37. /**
  38. * @property User $user
  39. * @property Order $order
  40. */
  41. class OrderPayDataForm extends Model
  42. {
  43. public $store_id;
  44. public $order_id;
  45. public $order_id_list;
  46. public $pay_type;
  47. public $user;
  48. public $form_id;
  49. public $parent_user_id;
  50. public $condition;
  51. public $_from;
  52. public $is_combine;
  53. /** @var Wechat $wechat */
  54. private $wechat;
  55. private $wechatPay;
  56. private $order;
  57. const PAY_FROM_APP = 'app';
  58. const PAY_FROM_MINI = 'mini';
  59. const PAY_FROM_H5 = 'h5';
  60. const PAY_FROM_OFFICIAL = 'official';
  61. const PAY_FROM_YUNST = 'yunst';
  62. public function rules()
  63. {
  64. return [
  65. [['pay_type', '_from'], 'required'],
  66. [['_from'], 'in', 'range' => ['app', 'mini', 'h5', 'official', 'yunst']],
  67. [['pay_type'], 'in', 'range' => [1, 2, 3, 4, 5, Order::PAY_TYPE_YUNST_WECHAT_PAY]], // 'WECHAT_PAY', 'HUODAO_PAY', 'BALANCE_PAY' 'ALIPAY',
  68. [['form_id', 'order_id_list', '_from'], 'string'],
  69. ['is_combine', 'default', 'value' => 0],
  70. [['parent_user_id', 'condition', 'order_id', 'is_combine'], 'integer'],
  71. ];
  72. }
  73. public function search()
  74. {
  75. //$this->wechatPay = \Yii::$app->controller->wechatPay;
  76. if (!$this->validate()) {
  77. return [
  78. 'code' => 1,
  79. 'msg' => $this->getErrorSummary(false)[0],
  80. ];
  81. }
  82. $t = \Yii::$app->db->beginTransaction();
  83. if ($this->order_id) { //单个订单付款
  84. $this->order = Order::findOne([
  85. 'id' => $this->order_id,
  86. ]);
  87. if (intval($this->order->is_pay)) {
  88. $t->rollBack();
  89. return [
  90. 'code' => 1,
  91. 'msg' => '订单已支付',
  92. ];
  93. }
  94. // 供应链系统下单时是否使用平台商户号,1使用,0未使用
  95. if (!Store::hasIncoming($this->order->store_id)) {
  96. $this->order->is_use_platform_mch = 1;
  97. $this->order->save();
  98. }
  99. //0元订单开始
  100. if ($this->order->pay_price == 0) {
  101. $this->order->pay_time = time();
  102. $this->order->is_pay = 1;
  103. $this->order->pay_type = 3;
  104. $this->order->trade_status = Order::ORDER_FLOW_NO_SEND;
  105. $this->order->save();
  106. $form = new AllianceOrderComplete();
  107. $form->order_id = $this->order->id;
  108. $form->order_type = 0;
  109. $form->store_id = $this->order->store_id;
  110. $form->notify();
  111. $t->commit();
  112. return [
  113. 'code' => 0,
  114. 'msg' => '支付成功'
  115. ];
  116. }
  117. //0元订单结束
  118. if (!$this->order) {
  119. $t->rollBack();
  120. return [
  121. 'code' => 1,
  122. 'msg' => '订单不存在',
  123. ];
  124. }
  125. if ($this->order->is_delete == 1 || $this->order->trade_status == Order::ORDER_FLOW_CANCEL) {
  126. $t->rollBack();
  127. return [
  128. 'code' => 1,
  129. 'msg' => '订单已取消',
  130. ];
  131. }
  132. if ($this->order->is_pay == 1 || $this->order->trade_status > -1) {
  133. $t->rollBack();
  134. return [
  135. 'code' => 1,
  136. 'msg' => '订单状态异常',
  137. ];
  138. }
  139. try {
  140. $this->checkGoodsConfine($this->order);
  141. } catch (\Exception $e) {
  142. $t->rollBack();
  143. return [
  144. 'code' => 1,
  145. 'msg' => $e->getMessage()
  146. ];
  147. }
  148. $goods_names = '';
  149. $goods_list = OrderDetail::find()->alias('od')->leftJoin(['g' => Goods::tableName()],
  150. 'g.id=od.goods_id')->where(['od.order_id' => $this->order->id, 'od.is_delete' => 0,
  151. ])->select('g.name,g.verify_card_id')->asArray()->all();
  152. foreach ($goods_list as $goods) {
  153. $goods_names .= $goods['name'] . ';';
  154. }
  155. $goods_names = mb_substr($goods_names, 0, 32, 'utf-8');
  156. //计算佣金
  157. //$this->setReturnData($this->order);
  158. $this->order->order_union_id = 0;
  159. if (!$this->order->save()) {
  160. $t->rollBack();
  161. return [
  162. 'code' => 1,
  163. 'msg' => '订单保存失败'
  164. ];
  165. }
  166. // 余额抵扣支付
  167. $balance_price = 0;
  168. $this->order->combine_money = 0;
  169. $this->order->is_combine_pay = Order::NOT_COMBINE_PAY;
  170. $this->order->save();
  171. if ($this->pay_type == 1 || $this->pay_type == Order::PAY_TYPE_YUNST_WECHAT_PAY || $this->pay_type == 4 || $this->pay_type == 5) {
  172. //0元支付开始
  173. if ($this->order->pay_price == 0) {
  174. $this->order->is_pay = 1;
  175. $this->order->pay_type = 1;
  176. if ($this->pay_type == 4) {
  177. $this->order->pay_type = 4;
  178. }
  179. $this->order->pay_time = time();
  180. if (!$this->order->save()) {
  181. $t->rollBack();
  182. return [
  183. 'code' => 1,
  184. 'msg' => '支付失败'
  185. ];
  186. }
  187. // 支付完成后,相关操作
  188. $form = new AllianceOrderComplete();
  189. $form->order_id = $this->order->id;
  190. $form->order_type = 0;
  191. //$form->store_id = get_store_id();
  192. $form->store_id = $this->order->store_id;
  193. $form->notify();
  194. $t->commit();
  195. return [
  196. 'code' => 0,
  197. 'msg' => '0元支付'
  198. ];
  199. }
  200. //0元支付结束
  201. if ($this->pay_type == 1) {
  202. // \Yii::error($this->_from);
  203. if ($this->_from == self::PAY_FROM_APP) {
  204. if (!Store::hasIncoming($this->order->store_id)) {
  205. $result = WechatPay::orderUnify($this->order,OrderNo::ORDER_ALLIANCE, $goods_names, 0, true, $balance_price);
  206. } else {
  207. $result = WechatAlliancePay::orderUnify($this->order,OrderNo::ORDER_ALLIANCE, $goods_names, 0, true, $balance_price);
  208. }
  209. } else if ($this->_from == self::PAY_FROM_H5) {
  210. if (!Store::hasIncoming($this->order->store_id)) {
  211. $result = WechatPay::orderUnify($this->order,OrderNo::ORDER_MALL, $goods_names, 0, false, $balance_price, true);
  212. } else {
  213. $result = WechatAlliancePay::orderUnify($this->order,OrderNo::ORDER_MALL, $goods_names, 0, false, $balance_price, true);
  214. }
  215. } else if ($this->_from == self::PAY_FROM_OFFICIAL) {
  216. if (!Store::hasIncoming($this->order->store_id)) {
  217. $result = WechatPay::orderUnify($this->order,OrderNo::ORDER_MALL, $goods_names, 0, false, $balance_price, false, true);
  218. } else {
  219. $result = WechatAlliancePay::orderUnify($this->order,OrderNo::ORDER_MALL, $goods_names, 0, false, $balance_price, false, true);
  220. }
  221. } else {
  222. if (!Store::hasIncoming($this->order->store_id)) {
  223. $result = WechatPay::orderUnify($this->order,OrderNo::ORDER_ALLIANCE, $goods_names, 0, false, $balance_price);
  224. } else {
  225. $result = WechatAlliancePay::orderUnify($this->order,OrderNo::ORDER_ALLIANCE, $goods_names, 0, false, $balance_price);
  226. }
  227. }
  228. if (isset($result['code']) && $result['code'] == 1) {
  229. if ($this->_from == self::PAY_FROM_OFFICIAL) {
  230. $result['wechat_platform_open_id'] = get_user()->wechat_platform_open_id;
  231. $result['h5_auth_link'] = LoginForm::getAuthLink();
  232. }
  233. return $result;
  234. }
  235. CloudPrint::doPrint($this->order->id, 0, $this->order->store_id);
  236. $t->commit();
  237. return [
  238. 'code' => 0,
  239. 'msg' => 'success',
  240. 'data' => (object)$result['data'],
  241. 'res' => $result['res'],
  242. 'body' => $goods_names
  243. ];
  244. }
  245. if ($this->pay_type == Order::PAY_TYPE_YUNST_WECHAT_PAY) {
  246. // if (!Store::hasIncoming($this->order->store_id, 'yunst')) {
  247. // return [
  248. // 'code' => 1,
  249. // 'msg' => '商家未配置通联支付'
  250. // ];
  251. // }
  252. //是非独立部署 进件流程//通联支付 start
  253. $store = Store::findOne(['id' => $this->order->store_id]);
  254. $OrderYunst = new OrderYunst();
  255. $result2 = $OrderYunst->payYunst($this->order->store_id, $this->order->order_no, $store->cusid, $this->order->pay_price * 100);
  256. if ($result2['subCode'] == 'SUCCESS') {
  257. $payInfo = json_decode($result2['data']['payinfo'], true);
  258. if (!empty($payInfo)) {
  259. if (is_array($payInfo)) {
  260. return [
  261. 'code' => 0,
  262. 'data' => $payInfo,
  263. 'msg' => 'success',
  264. 'res' => $payInfo
  265. ];
  266. }
  267. return [
  268. 'code' => 1,
  269. 'msg' => $result2['data']['errmsg']
  270. ];
  271. }
  272. return [
  273. 'code' => 1,
  274. 'msg' => $result2['subMsg']
  275. ];
  276. }
  277. return $result2;
  278. //通联支付 end
  279. }
  280. if ($this->pay_type == 4) {
  281. $user = ($this->user ?: get_saas_user());
  282. if ($this->_from == self::PAY_FROM_MINI) {
  283. //TODO 兼容
  284. //AlipayUnion
  285. if (is_profit_pay('ali')) {
  286. $result = AlipayUnion::mini($this->order, $goods_names, $user, '', '', false, 0, $balance_price);
  287. } else {
  288. $result = Alipay::mini($this->order, $goods_names, $user, '', '', 0, $balance_price);
  289. }
  290. if (isset($result['code']) && $result['code'] == 1) {
  291. return $result;
  292. }
  293. //$t->commit();
  294. return [
  295. 'code' => 0,
  296. 'msg' => 'success',
  297. 'data' => $result['data']['trade_no'],
  298. 'body' => $goods_names
  299. ];
  300. } else {
  301. if (is_profit_pay('ali')) {
  302. if ($this->order->store_id <= 0) {
  303. $result = AlipayUnion::app($this->order, $goods_names, $this->user, $balance_price);
  304. } else {
  305. $result = AlipayProfit::app($this->order, $goods_names, $this->user, $balance_price);
  306. }
  307. } else {
  308. $result = Alipay::app($this->order, $goods_names, $this->user, $balance_price);
  309. }
  310. if (isset($result['code']) && $result['code'] == 1) {
  311. //$t->commit();
  312. return $result;
  313. }
  314. //$t->commit();
  315. return [
  316. 'code' => 0,
  317. 'msg' => 'success',
  318. 'data' => $result['data'],
  319. 'body' => $goods_names
  320. ];
  321. }
  322. }
  323. // // 抖音小程序
  324. // if ($this->pay_type == 5) {
  325. // $result = ByteDance::pay($this->order, '', $goods_names, 0 , $balance_price);
  326. // if (isset($result['code']) && $result['code'] == 1) {
  327. // return $result;
  328. // }
  329. // //$t->commit();
  330. // return [
  331. // 'code' => 0,
  332. // 'msg' => 'success',
  333. // 'data' => $result['data'],
  334. // ];
  335. // }
  336. }
  337. // //货到付款和余额支付数据处理
  338. // if ($this->pay_type == 2 || $this->pay_type == 3) {
  339. // $order = $this->order;
  340. // // 中间页选择货到付款,需要存入支付类型
  341. // if ($this->pay_type == 2) {
  342. // $order->is_pay = 0;
  343. // $order->pay_type = 2;
  344. // $order->save();
  345. // }
  346. // // //余额支付 用户余额变动
  347. // // if ($this->pay_type == 3) {
  348. // // $user = User::findOne(['id' => $order->user_id]);
  349. // // if ($user->money < $order->pay_price) {
  350. // // $t->rollBack();
  351. // // return [
  352. // // 'code' => 1,
  353. // // 'msg' => '支付失败,余额不足',
  354. // // ];
  355. // // }
  356. // // // $user->money -= floatval($order->pay_price);
  357. // // $res = AccountLog::saveLog($user->id, floatval($order->pay_price), AccountLog::TYPE_BALANCE, AccountLog::LOG_TYPE_EXPEND, 1, $order->id, "商城余额支付,订单号为:{$order->order_no}。");
  358. // // if (!$res) {
  359. // // $t->rollBack();
  360. // // return [
  361. // // 'code' => 1,
  362. // // 'msg' => '支付失败'
  363. // // ];
  364. // // }
  365. // // $order->is_pay = 1;
  366. // // $order->pay_type = 3;
  367. // // $order->trade_status = Order::ORDER_FLOW_NO_SEND;
  368. // // $order->pay_time = time();
  369. // // if ($order->user_id != get_user_id()) {
  370. // // $order->pay_user_id = get_user_id();
  371. // // }
  372. // // if (!$order->save()) {
  373. // // $t->rollBack();
  374. // // return [
  375. // // 'code' => 1,
  376. // // 'msg' => '支付失败'
  377. // // ];
  378. // // }
  379. // // }
  380. // // 同城配送订单下单
  381. // if ($order->is_delivery == 1) {
  382. // $detail_goods = OrderDetail::find()->where(['order_id' => $order->id])->select('goods_name as name, pic, num, total_price as price')->asArray()->all();
  383. // Delivery::addOrder($detail_goods, $order->order_no);
  384. // }
  385. // // 支付完成后,相关操作
  386. // $form = new OrderComplete();
  387. // $form->order_id = $order->id;
  388. // $form->order_type = 0;
  389. // $form->store_id = $this->order->store_id;
  390. // $form->notify();
  391. // CloudPrint::doPrint($this->order->id, 0, $this->order->store_id);
  392. // //$t->commit();
  393. // return [
  394. // 'code' => 0,
  395. // 'msg' => '支付成功',
  396. // 'data' => ''
  397. // ];
  398. // }
  399. }
  400. }
  401. /**
  402. * 设置佣金
  403. * @param Order $order
  404. * @return mixed
  405. */
  406. private function setReturnData($order)
  407. {
  408. $form = new ShareMoneyForm();
  409. $form->order = $order;
  410. $form->order_type = 0;
  411. return $form->setData();
  412. }
  413. /**
  414. * @param Order $order
  415. * @throws \Exception
  416. */
  417. private function checkGoodsConfine($order)
  418. {
  419. $saas_user = get_saas_user();
  420. if ($order->user_id > 0) {
  421. $user = User::findOne($order->user_id);
  422. } else {
  423. if ($order->saas_id > 0) {
  424. $saas_user = SaasUser::findOne($order->saas_id);
  425. $user = User::findOne(['binding' => $saas_user->mobile, 'store_id' => get_store_id(), 'is_delete' => 0]);
  426. }
  427. }
  428. foreach ($order->detail as $detail) {
  429. /* @var Goods $goods*/
  430. /* @var OrderDetail $detail*/
  431. $goods = $detail->goods;
  432. if ($goods->confine_count && $goods->confine_count > 0) {
  433. $goodsNum = 0;
  434. if (!empty($user)) {
  435. $goodsNum = Goods::getBuyNum($user, $goods->id);
  436. }
  437. $goodsTotalNum = intval($goodsNum + $detail->num);
  438. if ($goodsTotalNum > $goods->confine_count) {
  439. throw new \Exception('商品:' . $goods->name . ' 超出购买数量', 1);
  440. }
  441. }
  442. //起订数量
  443. if (($goods['order_min_count'] && $goods['order_min_count'] > 0)) {
  444. if ($detail->num < $goods['order_min_count']) {
  445. throw new \Exception('商品:' . $goods->name . ' 起订数量' . $goods['order_min_count'], 1);
  446. }
  447. }
  448. if (in_array($order->order_type, [1, 2])) {
  449. $res = $this->bookCheckGoodsNum($goods, $detail, $order);
  450. if ($res['code'] > 0) {
  451. throw new \Exception($res['msg'], 1);
  452. }
  453. }
  454. }
  455. }
  456. /**
  457. * @param Goods $goods
  458. * @param OrderDetail $detail
  459. * @param Order $order
  460. */
  461. private function bookCheckGoodsNum($goods, $detail, $order) {
  462. // 判断时间
  463. if (time() - $order->created_at > 15 * 60) {
  464. return [
  465. 'code' => 1,
  466. 'msg' => '订单已过支付时间,将自动取消'
  467. ];
  468. }
  469. $attr = Json::decode($detail->attr);
  470. // 酒店预约
  471. if ($order->order_type == 1) {
  472. // $date_book = GoodsBook::findOne(['goods_id' => $goods->id])->date_book;
  473. // $date_book = Json::decode($date_book);
  474. // if (!$date_book) {
  475. // return [
  476. // 'code' => 1,
  477. // 'msg' => '数据异常'
  478. // ];
  479. // }
  480. // $data_config = array_combine(array_column($date_book, 'date'), array_column($date_book, 'num'));
  481. // foreach ($attr as $value) {
  482. // if (isset($data_config[$value['date']])) {
  483. // if ($data_config[$value['date']] < $detail->num) {
  484. // return [
  485. // 'code' => 1,
  486. // 'msg' => '选中日期' . $value['date'] . '内暂无房源'
  487. // ];
  488. // }
  489. // } else {
  490. // return [
  491. // 'code' => 1,
  492. // 'msg' => '未找到预约时间下相关商品数据'
  493. // ];
  494. // }
  495. // }
  496. }
  497. // 服务预约
  498. if ($order->order_type == 2) {
  499. $service_book = GoodsBook::findOne(['goods_id' => $goods->id])->service_book;
  500. $service_book = Json::decode($service_book);
  501. if (!$service_book) {
  502. return [
  503. 'code' => 1,
  504. 'msg' => '数据异常'
  505. ];
  506. }
  507. $date_data = $this->getDateByInterval(7);
  508. $count = 0;
  509. $new_arr = [
  510. 'data' => []
  511. ];
  512. $order = Order::find()->alias('o')
  513. ->leftJoin(['od' => OrderDetail::tableName()], 'o.id = od.order_id')
  514. ->where(['o.trade_status' => [0, 2, 3], 'o.is_delete' => 0, 'o.order_type' => 2, 'goods_id' => $goods['id']])
  515. ->andWhere(['>', 'o.created_at', strtotime(date("Y-m-d"))])
  516. ->select('od.attr, od.num')->asArray()->all();
  517. foreach ($date_data as $index => $datum) {
  518. $new_arr['data'][$index]['date'] = $datum;
  519. $new_arr['data'][$index]['time'] = $service_book['data'][0]['time'];
  520. }
  521. if (!$new_arr) {
  522. return [
  523. 'code' => 1,
  524. 'msg' => '数据异常'
  525. ];
  526. }
  527. $service_book = $new_arr['data'];
  528. $service_book_date = array_column($service_book, NULL, 'date');
  529. $service_book_time = $service_book_date[$attr['date']]['time'];
  530. $num = 0;
  531. $is = false;
  532. foreach ($order as $item) {
  533. $item['attr'] = json_decode($item['attr'], true);
  534. if ($item['attr']['date'] === $attr['date']) {
  535. if ($attr['time'] == $item['attr']['time']) {
  536. $num += $item['num'];
  537. }
  538. }
  539. }
  540. foreach ($service_book_time as $m) {
  541. foreach ($m['times'] as $n) {
  542. $is = true;
  543. if ($n['time'] == $attr['time']) {
  544. if (($detail->num + $num) > $n['num']) {
  545. return [
  546. 'code' => 1,
  547. 'msg' => $n['time'] . '时间段内暂不可预约'
  548. ];
  549. }
  550. }
  551. }
  552. }
  553. if ($is === false) {
  554. return [
  555. 'code' => 1,
  556. 'msg' => '未找到预约时间下相关商品数据'
  557. ];
  558. }
  559. }
  560. return [
  561. 'code' => 0,
  562. 'msg' => 'success'
  563. ];
  564. }
  565. public function getDateByInterval(int $num) :array
  566. {
  567. //var_dump($st, $et);die;
  568. $returnData = [];
  569. $i = 0;
  570. do {
  571. $temp = date('Y-m-d', strtotime('+' . $i . ' day', strtotime(date('Y-m-d'))));
  572. $returnData[] = $temp;
  573. $i++;
  574. } while ($i < $num);
  575. return $returnData;
  576. }
  577. }