PaymentController.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. <?php
  2. namespace api\modules\v1\controllers;
  3. use addons\Bargain\common\models\BargainOrder;
  4. use addons\CardCoupons\common\models\CardCouponsScoreGive;
  5. use addons\Coupon\common\enums\AddonsCouponEnum;
  6. use addons\Coupon\common\models\AddonsCoupon;
  7. use addons\Coupon\common\models\AddonsCouponUserRelate;
  8. use addons\Course\common\models\AddonsCourseOrders;
  9. use addons\GroupBuy\common\models\GroupBuyOrder;
  10. use addons\LaoDaFu\common\models\LaoDaFuStoreMedicalRecord;
  11. use addons\OperatingNote\common\models\AddonsOperatingNoteBuy;
  12. use addons\QianxiSupplyChain\common\models\QianxiSupplyChainOrder;
  13. use addons\TacticsPay\common\global_func\Payment;
  14. use api\controllers\OnAuthController;
  15. use api\services\PaymentService;
  16. use common\enums\AddonsEnum;
  17. use common\enums\AliPayPayTypeEnum;
  18. use common\enums\ApiStatusEnum;
  19. use common\enums\OrderStatusEnum;
  20. use common\enums\PaymentTradeOrderEnum;
  21. use common\enums\PayTypeEnum;
  22. use common\enums\StatusEnum;
  23. use common\globals\GlobalInvoke;
  24. use common\helpers\ArrayHelper;
  25. use common\logic\common\AddonsLimit;
  26. use common\models\common\Addons;
  27. use common\models\common\PaymentTrade;
  28. use common\models\common\PaymentTradeLog;
  29. use common\models\common\PaymentTradeOrder;
  30. use common\models\common\RechargeOrders;
  31. use common\models\order\Order;
  32. use common\models\order\OrderDetail;
  33. use common\models\order\OrderMarketing;
  34. use common\models\user\UserInfo;
  35. use common\models\user\UserWallet;
  36. use common\models\mall\MallAddons;
  37. use yii\web\Controller;
  38. use Yii;
  39. use Exception;
  40. use common\traits\BaseControllerTrait;
  41. use common\models\common\PaymentTradeGroupOrder;
  42. use addons\Cake\common\models\CakeOrder;
  43. use addons\BaiMiMovie\common\models\MovieOrder;
  44. use common\events\data\api\PaymentTypeEvent;
  45. use common\helpers\LockHelper;
  46. /**
  47. * 支付控制器
  48. *
  49. *
  50. * Class PaymentController
  51. * @package frontend\controllers
  52. */
  53. class PaymentController extends OnAuthController
  54. {
  55. public $enableCsrfValidation = false;
  56. public $modelClass = '';
  57. protected $authOptional = ['get-pay-type'];
  58. /**
  59. * 生成订单支付流水
  60. * @return mixed|void
  61. */
  62. public function actionCreate()
  63. {
  64. $post = Yii::$app->request->post();
  65. $validateService = Yii::$app->services->validate;
  66. $rules = [
  67. [['order_id', 'order_type'], 'required'],
  68. ['order_type', 'in', 'range' => ['goods'], 'message' => '订单类型不合法'],
  69. ];
  70. $labels = [
  71. 'order_id' => '订单ID',
  72. 'order_type' => '订单类型'
  73. ];
  74. $valid = $validateService->validate($post, $rules, $labels);
  75. if (!$valid) {
  76. return $this->error($validateService->getFirstErrorSummary());
  77. }
  78. $orders = [];
  79. $orderList = Order::find()->where(['id' => $post['order_id'], 'pay_status' => 0, 'order_status' => OrderStatusEnum::NOT_PAY])->all();
  80. foreach ($orderList as $info) {
  81. $orders[] = [
  82. 'order_no' => $info['order_no'],
  83. 'amount' => $info['pay_money'],
  84. 'title' => Order::getOrderTitle($info),
  85. 'order_type' => $post['order_type']
  86. ];
  87. }
  88. $res = Yii::$app->services->pay->createTrade($this->mall_id, $this->user_id, $orders);
  89. return $this->success('操作成功', $res);
  90. }
  91. /*
  92. * 支付接口
  93. * @return mixed|void
  94. */
  95. public function actionPay()
  96. {
  97. $key = sprintf('PaymentPay:%s', $this->user_id);
  98. try {
  99. if (LockHelper::fLock($key, 5)) throw new Exception('请勿频繁请求');
  100. $post = Yii::$app->request->post();
  101. $validateService = Yii::$app->services->validate;
  102. $rules = [
  103. [['trade_no', 'pay_type'], 'required'],
  104. [['period'], 'integer'],
  105. [['action', 'sms_code'], 'string'],
  106. [['transaction_password','source','is_pay_group','pay_group_list', 'order_ids', 'main_order_id', 'is_store_pay', 'pay_type', 'trade_type'], 'safe'],
  107. [['balance_desc_type'], 'integer']
  108. ];
  109. $valid = $validateService->validate($post, $rules);
  110. if (!$valid) {
  111. return $this->error($validateService->getFirstErrorSummary());
  112. }
  113. $trade_no = $post['trade_no']; //交易流水号
  114. //获取交易流水信息
  115. $trade = Yii::$app->services->pay->getByTradeNo($trade_no);
  116. if (!$trade || $trade->user_id != $this->user_id) {
  117. throw new Exception('交易不存在');
  118. }
  119. // 已支付
  120. if ($trade->is_pay) {
  121. throw new Exception('订单已支付');
  122. }
  123. if ($trade->isBindPayType()) {
  124. throw new Exception('支付方式已变更,请刷新页面重新支付');
  125. }
  126. $pay_type = $post['pay_type']; //支付方式 : 1,2,3
  127. $trade_type = $post['trade_type']; //交易类型
  128. $params['sms_code'] = $post['sms_code'] ?? ''; //汇聚快捷支付:短信验证码
  129. $params['period'] = $post['period'] ?? 0; // 花呗分期期数
  130. $params['is_store_pay'] = $post['is_store_pay'] ?? 0; // 是否门店支付
  131. $source = $post['source'] ?? 1;
  132. // 判断是否开启超级支付
  133. $is_tactics_pay = false;
  134. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_TACTICS_PAY)) {
  135. $tactics_setting = Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_TACTICS_PAY, 'basic');
  136. !empty($tactics_setting['is_enable']) && $is_tactics_pay = true;
  137. }
  138. $enable_pay_type = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform,$source,['pay_money' => $trade->pay_fee ?? 0, 'user_id' => $this->user_id]);
  139. $enable_pay_type_arr = array_column($enable_pay_type, null, 'pay_type');
  140. // 判断是否支持该支付方式
  141. if (array_diff(is_array($pay_type) ? $pay_type : [$pay_type] , array_column($enable_pay_type, 'pay_type')) && !$is_tactics_pay) {
  142. throw new Exception('不支持该支付方式');
  143. }
  144. // 余额支付,判断是否允许余额支付
  145. if ($pay_type == PayTypeEnum::BALANCE && (new PaymentService(['mall_id' => $this->mall_id]))->isExcludeBalance($trade_no, $source)) {
  146. throw new Exception('不支持该支付方式');
  147. }
  148. // 判断是否组合支付
  149. // if (is_array($pay_type)) {
  150. // $paymentOrderObj = PaymentTradeGroupOrder::class;
  151. // } else {
  152. $paymentOrderObj = PaymentTradeOrder::class;
  153. // }
  154. // $payment_order_list = $paymentOrderObj::findAll(['trade_id' => $trade->id]);
  155. $payment_order_list = $paymentOrderObj::findAll(['trade_id' => $trade->id]);
  156. $order_type = reset($payment_order_list)->order_type;
  157. $order_no_arr = array_column($payment_order_list, 'order_no');
  158. switch ($order_type) {
  159. case PaymentTradeOrderEnum::MAIN_ORDER:
  160. $counts = Order::find()->where(['order_no'=>$order_no_arr,'pay_status'=>0])->count();
  161. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  162. $counts = Order::find()->where(['order_no'=>$order_no_arr,'pay_status'=>0,'order_status'=>OrderStatusEnum::NOT_PAY])->count();
  163. if(!$counts){
  164. throw new Exception('待支付订单不存在');
  165. }
  166. break;
  167. case PaymentTradeOrderEnum::OPERATING_NOTE_ORDER:
  168. $counts = AddonsOperatingNoteBuy::find()->where(['order_no'=>$order_no_arr,'is_pay'=>0])->count();
  169. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  170. break;
  171. case PaymentTradeOrderEnum::QIAN_XI_SUPPLY_CHAIN:
  172. $counts = QianxiSupplyChainOrder::find()->where(['order_no'=>$order_no_arr,'order_status'=>0])->count();
  173. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  174. break;
  175. case PaymentTradeOrderEnum::COURSE_ORDER:
  176. $counts = AddonsCourseOrders::find()->where(['order_no'=>$order_no_arr,'order_status'=>0])->count();
  177. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  178. break;
  179. case PaymentTradeOrderEnum::LAO_DA_FU_MEDICAL_RECORD:
  180. $counts = LaoDaFuStoreMedicalRecord::find()->where(['order_no'=>$order_no_arr,'pay_at'=>0])->count();
  181. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  182. break;
  183. default:
  184. $params['order_type'] = $order_type;
  185. $params['order_no_arr'] = $order_no_arr;
  186. $params['payment_order_list'] = $payment_order_list;
  187. Yii::$app->services->globalFunction->orderCheck('orderCheck',$params);
  188. }
  189. //查询用户open_id
  190. $user_info = UserInfo::findOne(['user_id' => $this->user_id, 'status' => 1, 'platform' => $this->platform]);
  191. $params['openid'] = !empty($user_info) ? $user_info->openid : '';
  192. // 支付参数
  193. $params['transaction_password'] = $post['transaction_password']??'';
  194. $params['balance_desc_type'] = $post['balance_desc_type']??StatusEnum::DISABLED;
  195. $params['source'] = $source;
  196. // 组合支付先进行钱包支付
  197. if (is_array($all_pay_type = $pay_type)) {
  198. $service = new \services\common\MixedPayService(['mall_id' => $this->mall_id]);
  199. // 设置为组合支付
  200. $service->setIsPayGroup($trade);
  201. // 创建支付子订单
  202. $service->createTradeItem($trade, $all_pay_type, $trade_type);
  203. // 积分或余额以外的支付方式
  204. $pay_type = $service->getOnlinePayType($all_pay_type);
  205. // 先进行钱包支付
  206. $wallet_pay_type = $service->getWalletPayType($all_pay_type);
  207. $pay_type_action = $enable_pay_type_arr[$wallet_pay_type]['action'];
  208. $this->isPostOrderDetail($service->getTradeType($trade_type, $wallet_pay_type), $pay_type_action, $order_no_arr, $params);
  209. $res = Yii::$app->services->pay->$pay_type_action($trade, $trade_type, $params);
  210. // 添加调用记录
  211. PaymentTradeLog::addLog([
  212. 'trade_id' => $trade->id,
  213. 'pay_type' => $pay_type,
  214. 'trade_type' => $service->getTradeType($trade_type, $wallet_pay_type),
  215. 'api_result' => json_encode($res)
  216. ], $trade);
  217. // 剩余的交易类型
  218. $trade_type = $service->getTradeType($trade_type, $pay_type);
  219. }
  220. if (!$enable_pay_type_arr[$pay_type]['action'] && !$is_tactics_pay) {
  221. throw new Exception('支付方式不存在');
  222. }
  223. $pay_type_action = $enable_pay_type_arr[$pay_type]['action'] ?? '';
  224. //TODO: 改写成功公共调用
  225. $mall_pay_types = array_keys(PayTypeEnum::mallPayType());
  226. // 判断是否开启超级支付
  227. if ($is_tactics_pay && !in_array($pay_type, [PayTypeEnum::BALANCE, PayTypeEnum::SCORE])) {
  228. $params['trade'] = $trade;
  229. $params['trade_type'] = $trade_type;
  230. $params['mall_id'] = $this->mall_id;
  231. $params['user_id'] = $this->user_id;
  232. $params['app_platform'] = $this->platform;
  233. $params['pay_type'] = $pay_type;
  234. $res = Payment::pay($params);
  235. }else if (in_array($pay_type, $mall_pay_types)) {
  236. // 主商城本身支持的支付方式,直接调用 service
  237. // 支付宝且为js的支付方式,需要带上商品
  238. if($order_type == PaymentTradeOrderEnum::MAIN_ORDER) $this->isPostOrderDetail($trade_type, $pay_type_action, $order_no_arr, $params);
  239. $res = Yii::$app->services->pay->$pay_type_action($trade, $trade_type, $params);
  240. } else {
  241. // 不是主商城支持(通过插件或者其他方式扩展)的支付方式,走公共调用
  242. // $invoke_id = (\Yii::$app->params)['common_function']['payment'][$pay_type];
  243. // // dd($pay_type, $invoke_id);
  244. // $params['trade'] = $trade;
  245. // $params['trade_type'] = $trade_type;
  246. // $res = GlobalInvoke::exec($invoke_id, $this->mall_id, $params);
  247. $params['action'] = $post['action'] ?? $pay_type_action;
  248. $params['trade'] = $trade;
  249. $params['trade_type'] = $trade_type;
  250. $params['mall_id'] = $this->mall_id;
  251. $params['user_id'] = $this->user_id;
  252. $params['app_platform'] = $this->platform;
  253. $params['pay_type'] = $pay_type;
  254. $res = GlobalInvoke::exec(GlobalInvoke::INVOKE_PAYMENT,$this->mall_id,$params);
  255. }
  256. if (!in_array($pay_type, [PayTypeEnum::BALANCE, PayTypeEnum::SCORE])) {
  257. //添加调用记录
  258. PaymentTradeLog::addLog([
  259. 'trade_id' => $trade->id,
  260. 'pay_type' => $pay_type,
  261. 'trade_type' => $trade_type,
  262. 'api_result' => json_encode($res)
  263. ], $trade);
  264. } else {
  265. LockHelper::unFLock($key);
  266. // 余额支付,返回值是否特殊处理
  267. return $this->success('支付成功', [
  268. 'pay_fee' => $trade['pay_fee'],
  269. 'order_ids' => $post['order_ids'] ?? '',
  270. 'main_order_id' => $post['main_order_id'] ?? '',
  271. ]);
  272. }
  273. if (!empty($res['return_code']) && $res['return_code'] == 'FAIL') return $this->error($res['return_msg'], $res);
  274. if (!empty($res['result_code']) && $res['result_code'] == 'FAIL') return $this->error($res['err_code_des'], $res);
  275. $res['pay_fee'] = $trade['pay_fee'];
  276. $res['order_ids'] = $post['order_ids'] ?? '';
  277. $res['main_order_id'] = $post['main_order_id'] ?? '';
  278. LockHelper::unFLock($key);
  279. return $this->success('操作成功', $res, ApiStatusEnum::CODE_SUCCESS, JSON_BIGINT_AS_STRING);
  280. } catch (Exception $e) {
  281. LockHelper::unFLock($key);
  282. if($e->getMessage()=='您未设置支付密码'){
  283. return $this->error($e->getMessage(),[],ApiStatusEnum::CODE_ERROR_SETTING_PAY_PASSWORD);
  284. }
  285. if($e->getMessage()=='请输入交易密码'){
  286. return $this->error($e->getMessage(),[],ApiStatusEnum::CODE_ERROR_PAY_PASSWORD);
  287. }
  288. return $this->error($e->getMessage());
  289. }
  290. }
  291. /**
  292. * 获取支付类型
  293. *
  294. * @return void
  295. */
  296. public function actionGetPayType()
  297. {
  298. $wallet = UserWallet::getOne(
  299. [['user_id' => $this->user_id]], true, [], false, 'balance,score as total_score'
  300. );
  301. $source = $this->request->get('source', 1, 1);
  302. $trade_no = $this->request->get('trade_no', '');
  303. //判断是否有卡券插件
  304. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_CARD_COUPONS)) {
  305. $allMoney = CardCouponsScoreGive::find()
  306. ->where(['mall_id' => $this->mall_id, 'receive_user_id' => $this->user_id, 'status' => StatusEnum::ENABLED,'is_active'=>CardCouponsScoreGive::ACTIVATED,'is_open'=>CardCouponsScoreGive::OPEN])
  307. ->andWhere(['<=', 'start_at', time()])
  308. ->andWhere(['>=', 'end_at', time()])
  309. ->sum('can_use_money');
  310. $wallet['balance'] = bcadd($wallet['balance'],$allMoney,2);
  311. }
  312. $trade = PaymentTrade::findOne(['out_trade_no'=>$trade_no]);
  313. if(!empty($trade_no)){
  314. if(!empty($trade)){
  315. if($trade->pay_fee<=0){
  316. $pay_type_list = Yii::$app->services->pay->getEnablePayMentByZero($this->mall_id);
  317. return $this->success('操作成功', ['list' => $pay_type_list, 'wallet' => $wallet]);
  318. }
  319. $payment_trade_order = PaymentTradeOrder::getOne([
  320. ['trade_id' => $trade['id']],
  321. ['order_type'=>['order','cashier_order']]
  322. ]);
  323. //判断订单类型,判断是否为门店订单/门店收银台订单
  324. if(!empty($payment_trade_order)){
  325. switch ($payment_trade_order['order_type']){
  326. case 'order':
  327. $pre = $payment_trade_order['order_no'][0].$payment_trade_order['order_no'][1];
  328. if($pre=='st'){
  329. $source = 6;
  330. }
  331. break;
  332. case 'cashier_order':
  333. $source = 6;
  334. break;
  335. }
  336. }
  337. }
  338. }
  339. $pay_type_list = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform, $source, ['pay_money' => $trade->pay_fee ?? 0, 'user_id' => $this->user_id]);
  340. //支付限制
  341. if (isset($trade->limit_payment)&&!empty($trade->limit_payment)) {
  342. //排除系统的主要支付方式
  343. $pay_type_list_filter = array_filter($pay_type_list, function ($item) {
  344. return !in_array($item['pay_type'], [PayTypeEnum::BALANCE, PayTypeEnum::SCORE, PayTypeEnum::WECHAT, PayTypeEnum::ALI, PayTypeEnum::MIXED]);
  345. });
  346. $limit_payment = json_decode($trade->limit_payment, true);
  347. foreach ($pay_type_list as $key => $pay) {
  348. foreach ($limit_payment as $key_l => $lpay) {
  349. if ($lpay==$pay['pay_type'] && $lpay!=0){
  350. $pay_type_list_filter[]=$pay_type_list[$key];
  351. }
  352. }
  353. }
  354. $pay_type_list=$pay_type_list_filter;
  355. }
  356. //如果存在消费卡支付方式,则将消费卡金额写入wallet内
  357. foreach ($pay_type_list as $key => $value) {
  358. if ($value['pay_type'] == PayTypeEnum::CONSUMER_CARD) $wallet['consumer_card'] = $value['consumer_card'];
  359. }
  360. // 获取支付方式是否支持组合支付
  361. $service = new \services\common\MixedPayService(['mall_id' => $this->mall_id]);
  362. $pay_type_list = $service->getPayTypeList($trade, $pay_type_list, $wallet, $source); // 排除支付方式
  363. //监听插件修改支付方式是否可用
  364. $event = new PaymentTypeEvent($this->mall_id, $pay_type_list, $this->user_id);
  365. Yii::$app->services->events->dispatch($event);
  366. $pay_type_list = $event->getResultForm();
  367. $paymentService = new PaymentService(['mall_id' => $this->mall_id]);
  368. $paymentService->excludePayType((string)$trade_no, (int)$source, $pay_type_list);
  369. return $this->success('操作成功', ['list' => $pay_type_list, 'wallet' => $wallet]);
  370. }
  371. /**
  372. * 是否需要响应订单中的商品数据
  373. * @param $trade_type
  374. * @param $pay_type_action
  375. * @param $order_no_arr
  376. * @param $params
  377. * @return mixed
  378. */
  379. private function isPostOrderDetail($trade_type, $pay_type_action, $order_no_arr, &$params)
  380. {
  381. if ($trade_type == AliPayPayTypeEnum::JS && $pay_type_action == "alipay") {
  382. $order = Order::find()->where(['order_no'=>$order_no_arr,'pay_status'=>0])
  383. ->with(['detail' => function($query) {
  384. $query->select('order_id, goods_id, goods_name, price, num as quantity')->where(['order_status' => StatusEnum::DISABLED]);
  385. }])->asArray()->all();
  386. $params['goods_detail'] = [];
  387. foreach ($order as $item) {
  388. foreach ($item['detail'] as $value) {
  389. $params['goods_detail'][] = $value;
  390. }
  391. }
  392. }
  393. return $params;
  394. }
  395. /**
  396. * 生成组合订单支付流水
  397. * @return mixed|void
  398. */
  399. public function actionGroupCreate()
  400. {
  401. $post = Yii::$app->request->post();
  402. $validateService = Yii::$app->services->validate;
  403. $rules = [
  404. [['trade_id','pay_group_list'], 'required'],
  405. [['pay_type','order_type'], 'safe'],
  406. [['order_id'],'safe']
  407. ];
  408. $valid = $validateService->validate($post, $rules);
  409. if (!$valid) {
  410. return $this->error($validateService->getFirstErrorSummary());
  411. }
  412. if(empty($post['pay_group_list'])){
  413. return $this->error('支付类型错误');
  414. }
  415. $parent_trade_exist = PaymentTrade::find()->where(['parent_trade_id' => $post['trade_id']])->one();
  416. if(!empty($parent_trade_exist)){
  417. //已经存在组合支付
  418. return $this->error('已存在待支付订单');
  419. }
  420. $trade = PaymentTrade::find()->where(['id' => $post['trade_id'],'is_pay' => 0])->one();
  421. if(empty($trade)){
  422. return $this->error('支付订单不存在');
  423. }
  424. $order_type = $post['order_type'];
  425. if(empty($order_type)){
  426. $trade_order = PaymentTradeOrder::find()->where(['trade_id' => $trade['id'],'is_pay' => 0])->asArray()->one();
  427. if(empty($trade_order)) return $this->error('待支付订单不存在');
  428. $order_type = $trade_order['order_type'];
  429. if($order_type == Order::DEFAULT){
  430. $order_ids = explode(",", $post['order_id']);
  431. $group_order = [];
  432. foreach ($order_ids as $order_id) {
  433. /**
  434. * @var Order $order
  435. */
  436. $order = Order::find()->where(['id' => $order_id, 'pay_status' => 0, 'order_status' => OrderStatusEnum::NOT_PAY])->one();
  437. if(empty($order)){
  438. return $this->error('待支付订单不存在!');
  439. }
  440. $order_no = $order['order_no'];
  441. $title = Order::getOrderTitle($order);
  442. $group_order[] = [
  443. 'order_no' => $order_no,
  444. 'title' => $title,
  445. 'id' => $order->id
  446. ];
  447. }
  448. }else{
  449. $title = $trade['title'];
  450. $order_no = $trade_order['order_no'];
  451. }
  452. }elseif($order_type == AddonsEnum::ADDONS_NAME_CAKE){
  453. $order = CakeOrder::find()->where(['id' => $post['order_id'], 'pay_status' => 0, 'order_status' => OrderStatusEnum::NOT_PAY])->one();
  454. if(empty($order)){
  455. return $this->error('待支付订单不存在');
  456. }
  457. $order_no = $order['order_no'];
  458. $title = CakeOrder::getOrderTitle($order);
  459. }elseif($order_type == AddonsEnum::ADDONS_NAME_BAI_MI_MOVIE){
  460. $order = MovieOrder::find()->where(['id' => $post['order_id'], 'is_pay' => 0])->one();
  461. if(empty($order)){
  462. return $this->error('待支付订单不存在');
  463. }
  464. $order_no = $order['channel_order_no'];
  465. $title = mb_strlen($order->order_title) > 32 ? mb_substr($order->order_title, 0, 32) : $order->order_title;
  466. }else{
  467. return $this->error('未知订单类型');
  468. }
  469. $pay_type = !empty($post['pay_type']) ? $post['pay_type'] : 0;
  470. $result = [];
  471. $pay_money_list = array_column($post['pay_group_list'],'pay_money');
  472. $pay_fee = bcadd($trade['pay_fee'],$trade['rand_fee'],2);
  473. if(bccomp(array_sum($pay_money_list), $pay_fee,2) !== 0){
  474. return $this->error('支付金额错误');
  475. }
  476. foreach ($post['pay_group_list'] as $pay_group) {
  477. $orders = [];
  478. if (!empty($group_order)) {
  479. foreach ($group_order as $item) {
  480. $orders[] = [
  481. 'order_id' => $item['id'],
  482. 'order_no' => $item['order_no'],
  483. 'amount' => $pay_group['pay_money'],
  484. 'title' => $item['title'],
  485. 'order_type' => $order_type,
  486. //'notify_class' => 'common\logic\notify\Notify',
  487. ];
  488. }
  489. } else {
  490. $orders[] = [
  491. 'order_id' => $order['id'] ?? 0,
  492. 'order_no' => $order_no,
  493. 'amount' => $pay_group['pay_money'],
  494. 'title' => $title,
  495. 'order_type' => $order_type,
  496. //'notify_class' => 'common\logic\notify\Notify',
  497. ];
  498. }
  499. try{
  500. $res = Yii::$app->services->pay->createGroupTrade($this->mall_id, $this->user_id, array_values($orders),$post['trade_id'],$pay_type);
  501. $result[$pay_group['trade_type']] = $res;
  502. }catch(\Exception $e){
  503. return $this->error($e->getMessage());
  504. }
  505. }
  506. return $this->success('操作成功', $result);
  507. }
  508. /**
  509. * 获取组合支付类型
  510. *
  511. * @return void
  512. */
  513. public function actionGetPayTypeByGroup()
  514. {
  515. $params = \Yii::$app->request->get();
  516. $res = \Yii::$app->services->validate->validate($params, [
  517. [['pay_type','source'], 'required'],
  518. ]);
  519. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  520. $pay_type_list = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform, $params['source']);
  521. $new_list = [];
  522. foreach($pay_type_list as $key => $pay_type){
  523. if($pay_type['pay_type'] != $params['pay_type'] && $pay_type['pay_type'] != PayTypeEnum::MIXED){
  524. $new_list[] = $pay_type;
  525. }
  526. }
  527. return $this->success('操作成功', ['list' => $new_list]);
  528. }
  529. /**
  530. * 组合支付-获取支付方式
  531. *
  532. * @return void
  533. */
  534. public function actionGetPayTypeByMixed()
  535. {
  536. $params = \Yii::$app->request->get();
  537. $res = \Yii::$app->services->validate->validate($params, [
  538. [['source'], 'required'],
  539. ]);
  540. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  541. $pay_type_list = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform, $params['source']);
  542. $new_list = [];
  543. $mall_list = PayTypeEnum::mallParty();
  544. $new_list['mall_pay_types'] = [];
  545. $new_list['third_pay_types'] = [];
  546. foreach($pay_type_list as $key => $pay_type){
  547. if($pay_type['pay_type'] == PayTypeEnum::MIXED){
  548. continue;
  549. }
  550. if($pay_type['pay_type'] == PayTypeEnum::HUIFUPAY){
  551. //临时暂停汇付参与组合支付
  552. continue;
  553. }
  554. if(isset($mall_list[$pay_type['pay_type']])){
  555. $new_list['mall_pay_types'][] = $pay_type;
  556. }else{
  557. $new_list['third_pay_types'][] = $pay_type;
  558. }
  559. }
  560. $wallet = UserWallet::getOne(
  561. [['user_id' => $this->user_id]], true, [], false, 'balance,score as total_score'
  562. );
  563. return $this->success('操作成功', ['list' => $new_list,'wallet' => $wallet]);
  564. }
  565. /**
  566. * 支付订单号支付验证
  567. * @return void
  568. */
  569. public function actionPayVerify()
  570. {
  571. // 支付流水单号
  572. $trade_id = Yii::$app->request->post('trade_id', 0);
  573. if (empty($trade_id)) return $this->error('参数错误');
  574. $res = Yii::$app->services->pay->getPayVerify($trade_id);
  575. if (!$res) {
  576. return $this->error('订单支付失败');
  577. }
  578. return $this->success('订单支付成功');
  579. }
  580. }