PaymentController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <?php
  2. namespace addons\Area\api\modules\v1\controllers;
  3. use addons\Bargain\common\models\BargainOrder;
  4. use addons\Area\common\models\AreaOrder;
  5. use addons\CardCoupons\common\models\CardCouponsScoreGive;
  6. use addons\Course\common\models\AddonsCourseOrders;
  7. use addons\GroupBuy\common\models\GroupBuyOrder;
  8. use addons\OperatingNote\common\models\AddonsOperatingNoteBuy;
  9. use addons\QianxiSupplyChain\common\models\QianxiSupplyChainOrder;
  10. use api\controllers\OnAuthController;
  11. use common\enums\AddonsEnum;
  12. use common\enums\AliPayPayTypeEnum;
  13. use common\enums\ApiStatusEnum;
  14. use common\enums\OrderStatusEnum;
  15. use common\enums\PaymentTradeOrderEnum;
  16. use common\enums\PayTypeEnum;
  17. use common\enums\StatusEnum;
  18. use common\globals\GlobalInvoke;
  19. use common\models\common\Addons;
  20. use common\models\common\PaymentTrade;
  21. use common\models\common\PaymentTradeLog;
  22. use common\models\common\PaymentTradeOrder;
  23. use common\models\common\RechargeOrders;
  24. use common\models\order\Order;
  25. use common\models\user\UserInfo;
  26. use common\models\user\UserWallet;
  27. use common\models\mall\MallAddons;
  28. use yii\web\Controller;
  29. use Yii;
  30. use Exception;
  31. use common\traits\BaseControllerTrait;
  32. use common\models\common\PaymentTradeGroupOrder;
  33. use addons\Cake\common\models\CakeOrder;
  34. use addons\BaiMiMovie\common\models\MovieOrder;
  35. /**
  36. * 支付控制器
  37. *
  38. *
  39. * Class PaymentController
  40. * @package frontend\controllers
  41. */
  42. class PaymentController extends OnAuthController
  43. {
  44. public $enableCsrfValidation = false;
  45. public $modelClass = '';
  46. protected $authOptional = ['get-pay-type'];
  47. /*
  48. * 支付接口
  49. * @return mixed|void
  50. */
  51. public function actionPay()
  52. {
  53. try {
  54. $post = Yii::$app->request->post();
  55. $validateService = Yii::$app->services->validate;
  56. $rules = [
  57. [['trade_no', 'pay_type'], 'required'],
  58. [['pay_type', 'period'], 'integer'],
  59. [['trade_type', 'sms_code'], 'string'],
  60. [['transaction_password','source','is_pay_group','pay_group_list', 'order_ids', 'main_order_id', 'is_store_pay'], 'safe'],
  61. [['balance_desc_type'], 'integer']
  62. ];
  63. $valid = $validateService->validate($post, $rules);
  64. if (!$valid) {
  65. return $this->error($validateService->getFirstErrorSummary());
  66. }
  67. $params['model_type'] = 'Area';
  68. $trade_no = $post['trade_no']; //交易流水号
  69. //获取交易流水信息
  70. $trade = Yii::$app->services->pay->getByTradeNo($trade_no);
  71. if (!$trade || $trade->user_id != $this->user_id) {
  72. throw new Exception('交易不存在');
  73. }
  74. $pay_type = $post['pay_type']; //支付方式 : 1,2,3
  75. $trade_type = $post['trade_type']; //交易类型
  76. $params['sms_code'] = $post['sms_code'] ?? ''; //汇聚快捷支付:短信验证码
  77. $params['period'] = $post['period'] ?? 0; // 花呗分期期数
  78. $params['is_store_pay'] = $post['is_store_pay'] ?? 0; // 是否门店支付
  79. $source = $post['source'] ?? 1;
  80. $enable_pay_type = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform,$source);
  81. $enable_pay_type_arr = array_column($enable_pay_type, null, 'pay_type');
  82. if (!isset($enable_pay_type_arr[$pay_type])) {
  83. throw new Exception('不支持该支付方式');
  84. }
  85. //校验交易类型
  86. Yii::$app->services->pay->verifyTradeType($pay_type, $trade_type);
  87. if(!empty($post['is_pay_group'])){
  88. $paymentOrderObj = PaymentTradeGroupOrder::class;
  89. }else{
  90. $paymentOrderObj = PaymentTradeOrder::class;
  91. }
  92. $payment_order_list = $paymentOrderObj::findAll(['trade_id'=>$trade['id']]);
  93. // print_r($payment_order_list);exit;
  94. $order_type = $payment_order_list[0]['order_type'];
  95. $order_no_arr = array_column($payment_order_list,'order_no');
  96. switch ($order_type){
  97. case 'Area':
  98. $counts = AreaOrder::find()->where(['order_no'=>$order_no_arr,'is_pay'=>0])->count();
  99. if($counts!=count($payment_order_list)) throw new Exception('主订单不一致');
  100. break;
  101. default:
  102. $params['order_type'] = $order_type;
  103. $params['order_no_arr'] = $order_no_arr;
  104. $params['payment_order_list'] = $payment_order_list;
  105. Yii::$app->services->globalFunction->orderCheck('orderCheck',$params);
  106. }
  107. if ($trade->is_pay) {
  108. throw new Exception('订单已支付');
  109. }
  110. //查询用户open_id
  111. $user_info = UserInfo::findOne(['user_id' => $this->user_id, 'status' => 1, 'platform' => $this->platform]);
  112. $params['openid'] = !empty($user_info) ? $user_info->openid : '';
  113. if (!$enable_pay_type_arr[$pay_type]['action']) {
  114. throw new Exception('支付方式不存在');
  115. }
  116. $pay_type_action = $enable_pay_type_arr[$pay_type]['action'];
  117. $params['transaction_password'] = $post['transaction_password']??'';
  118. $params['balance_desc_type'] = $post['balance_desc_type']??StatusEnum::DISABLED;
  119. $params['source'] = $source;
  120. //TODO: 改写成功公共调用
  121. $mall_pay_types = array_keys(PayTypeEnum::mallPayType());
  122. if (in_array($pay_type, $mall_pay_types)) {
  123. // 主商城本身支持的支付方式,直接调用 service
  124. // 支付宝且为js的支付方式,需要带上商品
  125. if($order_type == PaymentTradeOrderEnum::MAIN_ORDER) $this->isPostOrderDetail($trade_type, $pay_type_action, $order_no_arr, $params);
  126. $res = Yii::$app->services->pay->$pay_type_action($trade, $trade_type, $params);
  127. } else {
  128. // 不是主商城支持(通过插件或者其他方式扩展)的支付方式,走公共调用
  129. // $invoke_id = (\Yii::$app->params)['common_function']['payment'][$pay_type];
  130. // // dd($pay_type, $invoke_id);
  131. // $params['trade'] = $trade;
  132. // $params['trade_type'] = $trade_type;
  133. // $res = GlobalInvoke::exec($invoke_id, $this->mall_id, $params);
  134. $params['action'] = $pay_type_action;
  135. $params['trade'] = $trade;
  136. $params['trade_type'] = $trade_type;
  137. $params['mall_id'] = $this->mall_id;
  138. $params['pay_type'] = $pay_type;
  139. $res = GlobalInvoke::exec(GlobalInvoke::INVOKE_PAYMENT,$this->mall_id,$params);
  140. }
  141. if (!in_array($pay_type, [PayTypeEnum::BALANCE, PayTypeEnum::SCORE])) {
  142. //添加调用记录
  143. PaymentTradeLog::addLog([
  144. 'trade_id' => $trade->id,
  145. 'pay_type' => $pay_type,
  146. 'trade_type' => $trade_type,
  147. 'api_result' => json_encode($res)
  148. ], $trade);
  149. } else {
  150. // 余额支付,返回值是否特殊处理
  151. return $this->success('支付成功', [
  152. 'pay_fee' => $trade['pay_fee'],
  153. 'order_ids' => $post['order_ids'] ?? '',
  154. 'main_order_id' => $post['main_order_id'] ?? '',
  155. ]);
  156. }
  157. if (!empty($res['return_code']) && $res['return_code'] == 'FAIL') return $this->error($res['return_msg'], $res);
  158. if (!empty($res['result_code']) && $res['result_code'] == 'FAIL') return $this->error($res['err_code_des'], $res);
  159. $res['pay_fee'] = $trade['pay_fee'];
  160. $res['order_ids'] = $post['order_ids'] ?? '';
  161. $res['main_order_id'] = $post['main_order_id'] ?? '';
  162. return $this->success('操作成功', $res, ApiStatusEnum::CODE_SUCCESS, JSON_BIGINT_AS_STRING);
  163. } catch (Exception $e) {
  164. if($e->getMessage()=='您未设置支付密码'){
  165. return $this->error($e->getMessage(),[],ApiStatusEnum::CODE_ERROR_SETTING_PAY_PASSWORD);
  166. }
  167. if($e->getMessage()=='请输入交易密码'){
  168. return $this->error($e->getMessage(),[],ApiStatusEnum::CODE_ERROR_PAY_PASSWORD);
  169. }
  170. return $this->error($e->getMessage());
  171. }
  172. }
  173. /**
  174. * 获取支付类型
  175. *
  176. * @return void
  177. */
  178. public function actionGetPayType()
  179. {
  180. $wallet = UserWallet::getOne(
  181. [['user_id' => $this->user_id]], true, [], false, 'balance,score as total_score'
  182. );
  183. $source = $this->request->get('source',1,1);
  184. $trade_no = $this->request->get('trade_no','');
  185. //判断是否有卡券插件
  186. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_CARD_COUPONS)) {
  187. $allMoney = CardCouponsScoreGive::find()
  188. ->where(['mall_id' => $this->mall_id, 'receive_user_id' => $this->user_id, 'status' => StatusEnum::ENABLED,'is_active'=>CardCouponsScoreGive::ACTIVATED,'is_open'=>CardCouponsScoreGive::OPEN])
  189. ->andWhere(['<=', 'start_at', time()])
  190. ->andWhere(['>=', 'end_at', time()])
  191. ->sum('can_use_money');
  192. $wallet['balance'] = bcadd($wallet['balance'],$allMoney,2);
  193. }
  194. $source = $this->request->get('source');
  195. $trade_no = $this->request->get('trade_no');
  196. if(!empty($trade_no)){
  197. $trade = PaymentTrade::findOne(['out_trade_no'=>$trade_no]);
  198. if(!empty($trade)){
  199. if($trade->pay_fee<=0){
  200. $pay_type_list = Yii::$app->services->pay->getEnablePayMentByZero($this->mall_id);
  201. return $this->success('操作成功', ['list' => $pay_type_list, 'wallet' => $wallet]);
  202. }
  203. $payment_trade_order = PaymentTradeOrder::getOne([
  204. ['trade_id' => $trade['id']],
  205. ['order_type'=>['order','cashier_order']]
  206. ]);
  207. //判断订单类型,判断是否为门店订单/门店收银台订单
  208. if(!empty($payment_trade_order)){
  209. switch ($payment_trade_order['order_type']){
  210. case 'order':
  211. $pre = $payment_trade_order['order_no'][0].$payment_trade_order['order_no'][1];
  212. if($pre=='st'){
  213. $source = 6;
  214. }
  215. break;
  216. case 'cashier_order':
  217. $source = 6;
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. $pay_type_list = Yii::$app->services->pay->getEnablePayment($this->mall_id, $this->platform, $source);
  224. //支付限制
  225. if (isset($trade->limit_payment)&&!empty($trade->limit_payment)) {
  226. //排除系统的主要支付方式
  227. $pay_type_list_filter = array_filter($pay_type_list, function ($item) {
  228. return !in_array($item['pay_type'], [PayTypeEnum::BALANCE, PayTypeEnum::SCORE, PayTypeEnum::WECHAT, PayTypeEnum::ALI, PayTypeEnum::MIXED]);
  229. });
  230. $limit_payment = json_decode($trade->limit_payment, true);
  231. foreach ($pay_type_list as $key => $pay) {
  232. foreach ($limit_payment as $key_l => $lpay) {
  233. if ($lpay==$pay['pay_type'] && $lpay!=0){
  234. $pay_type_list_filter[]=$pay_type_list[$key];
  235. }
  236. }
  237. }
  238. $pay_type_list=$pay_type_list_filter;
  239. }
  240. return $this->success('操作成功', ['list' => $pay_type_list, 'wallet' => $wallet]);
  241. }
  242. /**
  243. * 是否需要响应订单中的商品数据
  244. * @param $trade_type
  245. * @param $pay_type_action
  246. * @param $order_no_arr
  247. * @param $params
  248. * @return mixed
  249. */
  250. private function isPostOrderDetail($trade_type, $pay_type_action, $order_no_arr, &$params)
  251. {
  252. if ($trade_type == AliPayPayTypeEnum::JS && $pay_type_action == "alipay") {
  253. $order = Order::find()->where(['order_no'=>$order_no_arr,'pay_status'=>0])
  254. ->with(['detail' => function($query) {
  255. $query->select('order_id, goods_id, goods_name, price, num as quantity')->where(['order_status' => StatusEnum::DISABLED]);
  256. }])->asArray()->all();
  257. $params['goods_detail'] = [];
  258. foreach ($order as $item) {
  259. foreach ($item['detail'] as $value) {
  260. $params['goods_detail'][] = $value;
  261. }
  262. }
  263. }
  264. return $params;
  265. }
  266. }