BalanceController.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. <?php
  2. namespace api\modules\v1\controllers\user;
  3. use addons\MerchantAuth\common\models\MerchantAuthLog;
  4. use api\controllers\OnAuthController;
  5. use common\enums\ApiStatusEnum;
  6. use common\enums\UserWalletEnum;
  7. use common\enums\WithdrawEnum;
  8. use common\logic\user\ScoreLogic;
  9. use common\models\common\BalanceLog;
  10. use common\models\common\PlatformSetting;
  11. use common\models\mall\MallAddons;
  12. use common\models\user\User;
  13. use common\models\user\UserWallet;
  14. use common\models\user\UserWithdrawLog;
  15. use common\enums\StatusEnum;
  16. use common\enums\WithdrawWayEnum;
  17. use common\globals\GlobalInvoke;
  18. use common\models\wechat\WechatTransferLog;
  19. use Yii;
  20. use yii\helpers\Json;
  21. use yii\db\Exception;
  22. use common\models\user\UserPartitionRelationship;
  23. use services\common\UserWalletService;
  24. use common\helpers\BcHelper;
  25. use common\helpers\LockHelper;
  26. use common\models\common\UserBankCard;
  27. use common\models\user\UserFreezeCommission;
  28. use common\models\user\WithdrawsLimitLog;
  29. class BalanceController extends OnAuthController
  30. {
  31. public $modelClass = '';
  32. /**
  33. *
  34. * 不用进行登录验证的方法
  35. *
  36. * 例如: ['index', 'update', 'create', 'view', 'delete']
  37. * 默认全部需要验证
  38. *
  39. * @var array
  40. */
  41. // protected $authOptional = ['login', 'mobile-login', 'sms-code', 'register', 'up-pwd'];
  42. /**
  43. * 余额详情
  44. * @return mixed|void
  45. */
  46. public function actionDetail()
  47. {
  48. $user_wallet = UserWallet::findOne(['user_id' => $this->user_id]);
  49. $data['now_balance'] = $user_wallet['balance'] ?? 0;
  50. $data['today_income'] = BalanceLog::find()->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'change_type'=>'add'])
  51. ->andWhere(['between','created_at',strtotime(date('Y-m-d')),time()])->sum('change_num') ?? 0;
  52. //$data['today_income'] = 0;
  53. $data['withdraw_num'] = $user_wallet['balance_withdrawal'];
  54. $data['use_num'] = 0;
  55. $data['top_up_num'] = 0;
  56. $query = BalanceLog::find()->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'capital_type'=>UserWalletEnum::CONSUMPTION_ORDER]);
  57. $use_num = $query->andWhere(['source_table'=>'transaction','status'=>StatusEnum::ENABLED,'change_type'=>'sub'])->sum('change_num');
  58. $query = BalanceLog::find()->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'change_type'=>'add','from_type'=>UserWalletEnum::RECHARGE]);
  59. $top_up_num = $query->sum('change_num');
  60. $data['use_num'] = $use_num??0;
  61. $data['top_up_num'] = $top_up_num??0;
  62. $balance_config = Yii::$app->services->setting->mall->get($this->mall_id, 'balance');
  63. $data['is_balance_transfer'] = $balance_config['is_balance_transfer'] ?? 0;
  64. $data['is_balance_score'] = $balance_config['is_balance_score'] ?? 0;
  65. return $this->success('操作成功', $data);
  66. }
  67. /**
  68. * 余额充值/消费/提现记录
  69. * @return mixed|void
  70. */
  71. public function actionList()
  72. {
  73. $params = \Yii::$app->request->get();
  74. $res = Yii::$app->services->validate->validate($params, [
  75. [['type'], 'required', 'message' => 'type,必传'],
  76. [['start_date', 'end_date', 'capital_type', 'limit'], 'safe'],
  77. ]);
  78. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  79. $where = [];
  80. $where[] = ['mall_id' => $this->mall_id];
  81. $where[] = ['user_id' => $this->user_id];
  82. $where[]=['!=','status',-1];
  83. if($params['type'] == 2){
  84. $params['select'] = 'id,num as change_num,order_no,actual_num,poundage_num,exchange_score_num,type,status,created_at,content';
  85. $params['order'] = 'id desc';
  86. $where[] = ['from' => 2];
  87. $params['where'] = $where;
  88. $list = UserWithdrawLog::listPage($params);
  89. if($list['list']){
  90. $ids = array_column($list['list'], 'id');
  91. if ($this->platform == 'mp-wx') {
  92. $mini_program = Yii::$app->services->setting->mall->get($this->mall_id, 'mini_program', true);
  93. $appId = $mini_program['app_id'] ?? '';
  94. } else {
  95. $wechat_conf = Yii::$app->services->setting->mall->get($this->mall_id, 'wechat', true);
  96. $appId = $wechat_conf['app_id'] ?? '';
  97. }
  98. $wechat_transfer_log_list = \common\models\wechat\WechatTransferLog::lists(['where' => [['cash_id' => $ids]], 'index' => 'cash_id']);
  99. foreach ($list['list'] as &$v) {
  100. $v['transfer_result'] = [];
  101. if (isset($wechat_transfer_log_list[$v['id']])) {
  102. $payment_conf = \Yii::$app->services->setting->mall->get($this->mall_id, 'pay.wechat', true);
  103. $payment_conf = json_decode($payment_conf, true);
  104. $mchId = $payment_conf['wechat_mch_id'] ?? '';
  105. $wechat_transfer = $wechat_transfer_log_list[$v['id']];
  106. $transfer_result = json_decode($wechat_transfer['transfer_result'], true);
  107. $transfer_result['mchId'] = $mchId;
  108. $transfer_result['appId'] = $appId;
  109. $v['transfer_result'] = $transfer_result;
  110. }
  111. $content = json_decode($v['content'],true);
  112. $check_remark = '';
  113. $v['desc'] = '提现'.$v['change_num'];
  114. $v['created_at'] = date("Y-m-d H:i:s",$v["created_at"]);
  115. // 提现状态 0--申请 1--同意 2--已打款 3--驳回
  116. switch ($v['status']){
  117. case 0:
  118. $v['status_text'] = '申请';
  119. break;
  120. case 1:
  121. $v['status_text'] = '同意';
  122. break;
  123. case 2:
  124. $v['status_text'] = '已打款';
  125. break;
  126. case 3:
  127. $v['status_text'] = '驳回';
  128. $check_remark = $content['reject_content']??'';
  129. break;
  130. default:
  131. $v['status_text'] = '';
  132. break;
  133. }
  134. $v['check_remark'] = $check_remark;
  135. // 提现方式 auto--自动打款 wechat--微信打款 alipay--支付宝打款 bank--银行转账 balance--打款到余额
  136. switch ($v['type']){
  137. case 'auto':
  138. $v['type_text'] = '自动打款';
  139. break;
  140. case 'wechat':
  141. $v['type_text'] = '微信';
  142. break;
  143. case 'alipay':
  144. $v['type_text'] = '支付宝';
  145. break;
  146. case 'bank':
  147. $v['type_text'] = '银行转账';
  148. break;
  149. case 'balance':
  150. $v['type_text'] = '打款到余额';
  151. break;
  152. default:
  153. $v['type_text'] = '';
  154. break;
  155. }
  156. };
  157. }
  158. }else{
  159. if ($params['type'] == 3) {
  160. $where[] = ['change_type' => 'sub'];
  161. $where[] = ['from_type' => UserWalletEnum::CONSUME];//消费
  162. $where[] = ['source_table' => 'transaction'];//消费
  163. }
  164. if ($params['type'] == 1) {
  165. $where[] = ['change_type' => 'add'];
  166. $where[] = ['from_type' => UserWalletEnum::RECHARGE];//充值
  167. }
  168. if (!empty($params['start_date']) && !empty($params['end_date'])) {
  169. $params['end_date'] .= '23:59:59';
  170. $where[] = ['between','created_at',strtotime($params['start_date']),strtotime($params['end_date'])];
  171. }
  172. if (!empty($params['capital_type'])) {
  173. $where[] = ['capital_type' => $params['capital_type']];
  174. }
  175. $params['select'] = 'id,change_type,change_num,current_num,desc,created_at,user_id';
  176. $params['order'] = 'id desc';
  177. $params['where'] = $where;
  178. $list = BalanceLog::listPage($params);
  179. }
  180. return $this->success('操作成功', $list);
  181. }
  182. /**
  183. * 余额充值资金类型map
  184. * @return mixed|void
  185. */
  186. public function actionBalanceRechargeFrom()
  187. {
  188. return $this->success('操作成功', UserWalletEnum::getRechargeCapitalTypeMap());
  189. }
  190. /**
  191. * 余额/佣金提现
  192. * from 1/佣金 2/余额
  193. * User: wniu
  194. * Date: 2021/10/26
  195. * Time: 3:31 下午
  196. *
  197. * @throws \Exception
  198. */
  199. public function actionWithdraw()
  200. {
  201. $key = sprintf('Withdraw:%s', $this->user_id);
  202. if (LockHelper::fLock($key)) return $this->error('请勿频繁请求');
  203. $params = \Yii::$app->request->post();
  204. $params['mall_id'] = $this->mall_id;
  205. $params['user_id'] = $this->user_id;
  206. $params['need_auth'] = 1;
  207. $params['MerchantAuth'] = 1;
  208. try {
  209. UserWithdrawLog::withdrawCheck($params,$key);
  210. }catch (\Exception $e){
  211. LockHelper::unFLock($key);
  212. return $this->error($e->getMessage());
  213. }
  214. $form = new UserWithdrawLog();
  215. $params['mall_id'] = $this->mall_id;
  216. $params['user_id'] = $this->user_id;
  217. $params['x-app-platform'] = $this->platform;
  218. $form->attributes = $params;
  219. $data = $form->saveRecord($params);
  220. if($data['state']) {
  221. LockHelper::unFLock($key);
  222. return $this->success('操作成功', $data['data']);
  223. } else {
  224. LockHelper::unFLock($key);
  225. return $this->error($data['msg']);
  226. }
  227. }
  228. /**
  229. * @Author: 广东七件事 ganxiaohao
  230. * @Date: 2020-05-29
  231. * @Time: 19:40
  232. * @Note:提现相关设置
  233. */
  234. public function actionCashSetting()
  235. {
  236. $params = \Yii::$app->request->post();
  237. $res = Yii::$app->services->validate->validate($params, [
  238. [['from'], 'required', 'message' => '参数丢失'],
  239. [['from'], 'in', 'range' => [1, 2, 3,4]],
  240. [['source'], 'safe'],
  241. ]);
  242. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  243. $user_balance = UserWallet::getOne([['user_id' => $this->user_id, 'status' => 1]], true, [], false, 'balance,commission,score');
  244. $is_need_redirect = 0;
  245. $repurchase_redirect_url = '';
  246. $repurchase_prompt = '';
  247. $pay_password_status = 0;
  248. $is_hidden_money_unit = 0;
  249. if($params['from'] == 1) {//佣金
  250. $payment = \Yii::$app->services->setting->mall->get($this->mall_id, 'withdraw_income');
  251. if (!$payment) {
  252. return $this->error('暂未开启提现功能');
  253. }
  254. $isCash = $payment["is_income_cash"];
  255. $cashType = $payment['cash_type'];
  256. $cashServiceFee = isset($payment["cash_service_fee"]) ? $payment["cash_service_fee"] : 10;
  257. $cashIncomeServiceFee = isset($payment["cash_income_service_fee"]) ? $payment["cash_income_service_fee"] : 10;
  258. $minMoney = $payment['min_money'];
  259. $maxMoney = $payment['day_max_money'];
  260. $withdrawal_rule = isset($payment['profit_withdrawal_rule']) ? $payment['profit_withdrawal_rule'] : '手续费费率';
  261. $withdrawal_multiple = isset($payment['income_cash_multiple']) ? $payment['income_cash_multiple'] : 0;
  262. $userMoney = $user_balance['commission'];
  263. $freeze_commission = UserFreezeCommission::handlePromotionCenter($this->mall_id, $this->user_id);
  264. if (!empty($freeze_commission['is_freeze_commission'])) {
  265. $userMoney -= $freeze_commission['freeze_amount'];
  266. $userMoney < 0 && $userMoney = 0;
  267. }
  268. $is_show_balance_withdraws_limit_text = (int)((new UserWithdrawLog())->inBalanceWithdrawTotalWeightLimitSelectedByType($params['from'], WithdrawEnum::LIMIT_STRATEGY, $payment)); // 提现到余额是否需要显示可提现文案
  269. $withdraws_limit_enable = isset($payment["withdraws_limit_enable"]) ? $payment["withdraws_limit_enable"] : 0;
  270. $withdraws_limit_money = isset($payment["withdraws_limit_money"]) && is_numeric($payment["withdraws_limit_money"]) ? $payment["withdraws_limit_money"] : 0;
  271. $is_independent_balance_withdraw = $payment["is_independent_balance_withdraw"] ?? 0; // 是否开启独立余额提现
  272. $withdrawsLimitLogs = WithdrawsLimitLog::lists([
  273. 'where' => [
  274. ['user_id' => $this->user_id, 'status' => StatusEnum::ENABLED, 'from' => 1]
  275. ],
  276. 'select' => 'amount, type',
  277. 'index' => 'type'
  278. ]);
  279. if (!empty($withdraws_limit_enable)) {
  280. if (isset($withdrawsLimitLogs[WithdrawsLimitLog::COMMON_LIMIT]['amount'])) {
  281. $withdraws_limit_money = $withdrawsLimitLogs[WithdrawsLimitLog::COMMON_LIMIT]['amount'];
  282. }
  283. if ($is_independent_balance_withdraw) {
  284. $independent_balance_withdraw_max_amount = $withdrawsLimitLogs[WithdrawsLimitLog::BALANCE_LIMIT]['amount'] ?? ($payment['independent_balance_withdraw_max_amount'] ?? 0);
  285. } else {
  286. $independent_balance_withdraw_max_amount = $withdraws_limit_money;
  287. }
  288. $independent_balance_withdraw_max_amount = max($independent_balance_withdraw_max_amount, 0);
  289. }
  290. $difference = UserWithdrawLog::doRepurchaseCheck($payment, $this->user, $this->mall_id);
  291. if ($difference < 0) {
  292. $is_need_redirect = 1;
  293. $repurchase_redirect_url = $payment['repurchase_redirect_url'];
  294. $repurchase_prompt = '您需复购' . abs($difference) . '元,就能提现';
  295. }
  296. $pay_password_status = $payment['enable_password'] ?? 0;
  297. $is_hidden_money_unit = $payment['is_hidden_money_unit'] ?? 0;
  298. //todo 获取可提现佣金-待优化成功事件调用
  299. if (!empty($params['source']) && MallAddons::isInstall($this->mall_id, $params['source'])) {
  300. switch ($params['source']) {
  301. case 'FireProtection':
  302. $fire_protection_user = \addons\FireProtection\common\models\FireProtectionUser::findOne(['user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]);
  303. if (isset($fire_protection_user)) {
  304. $userMoney = $fire_protection_user['withdrawable_money'];
  305. }
  306. break;
  307. }
  308. }
  309. }elseif ($params['from'] == 4) {
  310. //积分提现
  311. $payment = \Yii::$app->services->setting->mall->get($this->mall_id, 'score');
  312. if (!$payment || !$payment['score_cash_status']) {
  313. return $this->error('暂未开启提现功能');
  314. }
  315. $isCash = $payment["score_cash_status"];
  316. $cashType = $payment['score_cash_type'];
  317. $cashServiceFee = $payment["score_cash_service_fee"] ?? 10;
  318. $minMoney = $payment['score_cash_min_money'];
  319. $maxMoney = $payment['score_cash_day_max_money'] ?? 0;
  320. $withdrawal_rule = '手续费费率';
  321. $withdrawal_multiple = 0;
  322. $userMoney = $user_balance['score'];
  323. //$show_notice = '您有1000积分,可用积分为200,10积分=1元,可提现20元';
  324. $radio = $payment['score_cash_radio'] ?? 1;
  325. $score_cash_today_limit = $payment['score_cash_today_limit'] ?? 0;
  326. $score_can_cash_arr = ScoreLogic::userTodayCanCashNum($this->mall_id,$this->user_id);
  327. $show_notice = '您有'.$userMoney.'积分,可用积分为'.$score_can_cash_arr['can_cash_num'].','.$radio.'积分=1元,可提现'.$score_can_cash_arr['can_cash_price'].'元';
  328. $score_cash_today_limit = $payment['score_cash_today_limit'] ?? 0;
  329. $question_mark = '';
  330. if($score_cash_today_limit > 0) $question_mark = '每天可提现的积分不超过00:00所持积分的'.$score_cash_today_limit.'%';
  331. if($maxMoney > 0){
  332. $question_mark = ($question_mark ? $question_mark.',' :'').'每日提现金额上限为'.$maxMoney.'元';
  333. }
  334. $userMoney = $score_can_cash_arr['can_cash_num'];
  335. $withdraws_limit_enable = 0;
  336. $withdraws_limit_money = 0;
  337. $pay_password_status = $payment['enable_password'] ?? 0;
  338. }else{
  339. $payment = \Yii::$app->services->setting->mall->get($this->mall_id, 'withdraw_balance');
  340. if (!$payment) {
  341. return $this->error('暂未开启提现功能');
  342. }
  343. $isCash = $payment["balance_cash_status"];
  344. $cashType = $payment['balance_cash_type'];
  345. $cashServiceFee = isset($payment["balance_cash_service_fee"]) ? $payment["balance_cash_service_fee"] : 10;
  346. $minMoney = $payment['balance_min_money'];
  347. $maxMoney = $payment['balance_day_max_money'];
  348. $withdrawal_rule = isset($payment['profit_withdrawal_rule']) ? $payment['profit_withdrawal_rule'] : '手续费费率';
  349. $withdrawal_multiple = isset($payment['balance_cash_multiple']) ? $payment['balance_cash_multiple'] : 0;
  350. $userMoney = $user_balance['balance'];
  351. $withdraws_limit_enable = 0;
  352. $withdraws_limit_money = 0;
  353. $pay_password_status = $payment['enable_password'] ?? 0;
  354. }
  355. // $balance_config = \Yii::$app->services->setting->mall->get($this->mall_id, 'pay.balance');
  356. // $pay_password_status = 0;
  357. // if ($balance_config) {
  358. // $balance_config = Json::decode($balance_config);
  359. // $pay_password_status = isset($balance_config["pay_password_status"]) ? $balance_config["pay_password_status"] : 0;
  360. // }
  361. if (!$isCash) {
  362. return $this->error('系统未开启提现功能');
  363. }
  364. if (!$cashType) {
  365. return $this->error('系统未设置提现方式');
  366. }
  367. $cash__type_name = [];
  368. $get_system_setting = PlatformSetting::getConfByGroup('system', true);
  369. if(!empty($cashType)){
  370. $cash_type = Json::decode($cashType);
  371. $cash__type_name = [];
  372. $default_withdraw_way = WithdrawWayEnum::getDefaultWithDrawWayMap(WithdrawWayEnum::WITHDRAW_TYPE_2);
  373. $extension_withdraw_way = GlobalInvoke::exec(GlobalInvoke::INVOKE_GET_WITHDRAW_EXTENSION_WAY,$this->mall_id,['mall_id'=>$this->mall_id]);
  374. $all_withdraw = array_merge($default_withdraw_way,$extension_withdraw_way);
  375. $cash_type_keys = array_keys($all_withdraw);
  376. if (in_array('bank', $cash_type_keys) || in_array('joinpay', $cash_type_keys)) {
  377. $bank_card_list = UserBankCard::getUserCardList($this->user_id, $this->mall_id);
  378. }
  379. // dd($cash_type);
  380. foreach ($cash_type as $i => $item) {
  381. if(isset($all_withdraw[$item])){
  382. $taxFee = 0;
  383. $name = '';
  384. if(isset($all_withdraw[$item])){
  385. if(is_array($all_withdraw[$item])){
  386. $name = $all_withdraw[$item]['name']??'';
  387. $taxFee = $all_withdraw[$item]['taxFee']??0;
  388. }else{
  389. $name = $all_withdraw[$item];
  390. }
  391. }
  392. $cash__type_name[$i]['type'] = $item;
  393. $cash__type_name[$i]['taxFee'] = $taxFee;
  394. $cash__type_name[$i]['name'] = $name;
  395. $cash__type_name[$i]['img'] = $get_system_setting['api_url']['value'].'/resources/img/payment/'.$item.'.png';
  396. if ('bank' == $item || 'joinpay' == $item || 'yunfast_pay' == $item) {
  397. $cash__type_name[$i]['bank_card_list'] = $bank_card_list;
  398. }
  399. }
  400. }
  401. }
  402. $password = User::getOne([['id' => $this->user_id]], true, '', '', 'transaction_password');
  403. $isTransactionPassword = false;
  404. $transaction_password = $password['transaction_password'];
  405. $transaction_password = trim($transaction_password);
  406. if(!empty($transaction_password)){
  407. $isTransactionPassword = true;
  408. }
  409. //检测是否需要实名认证
  410. $need_auth = GlobalInvoke::exec(GlobalInvoke::REAL_AUTH, $this->mall_id, ['user_id' => $this->user_id,'mall_id' => $this->mall_id,'type' => 'cash']);
  411. if($need_auth === true){
  412. //需要先进行实名认证
  413. return $this->error('请先进行实名认证',[],ApiStatusEnum::CODE_ERROR_NEED_REAL_AUTH);
  414. }
  415. $userWithdrawLog = UserWithdrawLog::getOne([
  416. ['user_id'=>$this->user_id],
  417. ['type'=>['alipay_tax','alipay']]
  418. ],true,[],'id desc');
  419. $aliAccountInfo = [];
  420. if(!empty($userWithdrawLog)){
  421. $extra = json_decode($userWithdrawLog['extra'],true);
  422. if(!empty($extra)){
  423. $aliAccountInfo = [
  424. 'name'=>$extra['name'],
  425. 'mobile'=>$extra['mobile'],
  426. 'id_card'=>$extra['id_card']??'',
  427. ];
  428. }
  429. }
  430. //商家认证
  431. $addons_auth = [];
  432. if(MallAddons::isInstall($this->mall_id,'MerchantAuth')){
  433. $configs = Yii::$app->services->setting->addons->get($this->mall_id, 'MerchantAuth', 'basic');
  434. $is_pass = 1;
  435. if(!empty($configs['is_force'])){
  436. //强制需要认证
  437. $res = MerchantAuthLog::getOne([
  438. ['mall_id'=>$this->mall_id],
  439. ['user_id'=>$this->user_id],
  440. ['status'=>1]
  441. ]);
  442. if(empty($res) || empty($res['progress'])) {
  443. $is_pass = 0;
  444. }elseif ($configs['is_force'] == 2 && $res['progress'] != 2) {
  445. $is_pass = 0;
  446. }
  447. }
  448. $addons_auth[] = ['addons'=>'MerchantAuth','is_pass' => $is_pass];
  449. }
  450. return $this->success('操作成功', [
  451. 'addons_auth'=>$addons_auth,
  452. 'notice'=>[
  453. 'content'=>'',
  454. 'icon'=>''
  455. ],
  456. 'setting' => [
  457. 'cash_type_name' => $cash__type_name,
  458. 'cash_service_fee' => $cashServiceFee,
  459. 'min_money' => $minMoney,
  460. 'cash_income_service_fee' => isset($cashIncomeServiceFee) ? $cashIncomeServiceFee : 0,
  461. 'day_max_money' => $maxMoney,
  462. 'withdrawal_rule' => $withdrawal_rule,
  463. 'pay_password_status' => intval($pay_password_status),
  464. 'multiple' => $withdrawal_multiple ?? 0,
  465. 'withdraws_limit_enable' => $withdraws_limit_enable ?? 0,
  466. 'withdraws_limit_money' => $withdraws_limit_money ?? 0,
  467. 'is_independent_balance_withdraw' => $is_independent_balance_withdraw ?? 0,
  468. 'independent_balance_withdraw_max_amount' => $independent_balance_withdraw_max_amount ?? 0,
  469. 'is_show_balance_withdraws_limit_text' => $is_show_balance_withdraws_limit_text ?? 1,
  470. 'is_hidden_money_unit' => $is_hidden_money_unit,
  471. 'show_notice' => $show_notice ?? '',
  472. 'question_mark' => $question_mark ?? ''
  473. ],
  474. 'user_info' => [
  475. 'income' => $userMoney,
  476. 'is_transaction_password' => $isTransactionPassword
  477. ],
  478. 'ali_account_info'=>$aliAccountInfo,
  479. 'repurchase_limit'=>[
  480. 'is_need_redirect' => $is_need_redirect,
  481. 'repurchase_redirect_url' => $repurchase_redirect_url,
  482. 'repurchase_prompt' => $repurchase_prompt
  483. ]
  484. ], ApiStatusEnum::CODE_SUCCESS, 0);
  485. }
  486. /**
  487. * 余额转送/转入页面
  488. * @Author: lun
  489. * @DateTime: 2021/11/24 0024 11:04
  490. * @Copyright: copyright (c) 2021 广东七件事集团
  491. * @return mixed|void
  492. */
  493. public function actionTransfer()
  494. {
  495. $form = Yii::$app->request->get();
  496. $rules = [[['type'], 'required'], [['type'], 'in', 'range' => ['score', 'balance']]];
  497. $res = Yii::$app->services->validate->validate($form, $rules);
  498. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  499. // 查询用户余额
  500. $score = UserWallet::find()->select('balance')->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'status'=>StatusEnum::ENABLED])->scalar();
  501. // 获取转送配置
  502. $config = Yii::$app->services->setting->mall->get($this->mall_id, 'balance');
  503. $score_name = Yii::$app->services->setting->mall->get($this->mall_id, 'score.score_name');
  504. if ($form['type'] == 'balance') {
  505. $ratio = $config['forwarding_charge'];
  506. $explain = "转送手续费:{$ratio}%";
  507. } elseif ($form['type'] == 'score') {
  508. $ratio = $config['balance_score_ratio'];
  509. $explain = "1元兑换{$ratio}个{$score_name}";
  510. }
  511. $pay_password_status = $config['enable_password'] ?? 0;
  512. $transaction_password = User::find()->select('transaction_password')->where(['mall_id'=>$this->mall_id,'id'=>$this->user_id,'status'=>StatusEnum::ENABLED])->scalar();
  513. $is_transaction_password = empty(trim($transaction_password)) ? false : true;
  514. $data = ['capital' => $score, 'explain' => $explain, 'ratio' => $ratio];
  515. $data = array_merge($data, compact('pay_password_status', 'is_transaction_password'));
  516. return $this->success('操作成功', $data);
  517. }
  518. /**
  519. * 余额转送提交
  520. * @Author: lun
  521. * @DateTime: 2021/11/24 0024 11:08
  522. * @Copyright: copyright (c) 2021 广东七件事集团
  523. * @return mixed|void
  524. */
  525. public function actionTransferBalance()
  526. {
  527. if (Yii::$app->request->isPost) {
  528. $form = Yii::$app->request->post();
  529. $rules = [
  530. [['balance','user_id'], 'required'],
  531. [['balance','user_id'], 'integer'],
  532. [['balance'], 'compare', 'compareValue' => 0, 'operator' => '>'],
  533. [['transaction_password'], 'string'],
  534. ];
  535. $res = Yii::$app->services->validate->validate($form, $rules);
  536. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  537. $key = sprintf('TransferBalance:%s', $this->user_id);
  538. try {
  539. if (LockHelper::fLock($key, 3)) throw new Exception('请勿频繁请求');
  540. // 检测转送用户是否是本人
  541. if ($form['user_id'] == $this->user_id) throw new Exception('赠送的用户不能是本人哦');
  542. // 检查用户是否存在
  543. $receive_user = User::getUser([['id' => $form['user_id']]], 'id');
  544. if (empty($receive_user)) throw new Exception('赠送的用户不存在');
  545. // 获取配置
  546. $config = Yii::$app->services->setting->mall->get($this->mall_id, 'balance');
  547. if (empty($config['is_balance_transfer'])) throw new Exception('余额转增功能尚未开启');
  548. $check_password_result = UserWithdrawLog::checkPassword($this->user_id, $form['transaction_password'], $config);
  549. if(is_array($check_password_result)){
  550. throw new Exception($check_password_result['msg']);
  551. }
  552. if (!empty($config['balance_transfer_permission'])) {
  553. $parent_ids = UserPartitionRelationship::getParentIdArr($this->user_id);// 获取上级
  554. $child_ids = UserPartitionRelationship::getChildIdArr($this->user_id);// 获取下级
  555. if (!in_array($receive_user->id, array_merge($parent_ids, $child_ids))) throw new Exception('转送会员不在你的团队中');
  556. }
  557. $fee = bcdiv($form['balance'] * $config['forwarding_charge'], 100, 2);// 手续费
  558. $sub_balance = bcadd($form['balance'], $fee, 2);// 最终扣减余额额度
  559. $give_user = $this->user_id;// 转出用户
  560. $receive = '用户:'.$receive_user->id;// 接收用户
  561. $fee_str = $fee <= 0 ? '' : ',手续费'.$fee;
  562. // 查询用户余额
  563. $user_wallet = UserWallet::find()->select('id,balance')->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'status'=>StatusEnum::ENABLED])->asArray()->one();
  564. if (empty($user_wallet) || ($user_wallet['balance'] < $sub_balance)) throw new Exception('余额额度不足');
  565. // 组合用户
  566. $list = [['user_id'=>$this->user_id,'type' => 'sub'], ['user_id'=>$receive_user->id,'type'=>'add']];
  567. //循环生成
  568. foreach ($list as $item) {
  569. $insert_wallet[] = [
  570. 'mall_id' => $this->mall_id,
  571. 'user_id' => $item['user_id'],
  572. 'is_frozen' => false,
  573. 'wallet_type' => UserWalletService::WALLET_TYPE_BALANCE,
  574. 'money' => $item['type'] == 'sub' ? -$sub_balance : $form['balance'],
  575. // 'desc' => $item['type'] == 'sub' ? '余额转送'. $form['balance'].'元,手续费'.$fee : '余额转送'. $form['balance'].'元',
  576. 'desc' => $item['type'] == 'sub' ? '余额转给'.$receive.$fee_str : $give_user.'余额转送',
  577. 'source_table' => UserWallet::tableName(),
  578. 'source_table_id' => $user_wallet['id'],
  579. 'from_type' => UserWalletEnum::TRANSFER,
  580. 'capital_type'=> UserWalletEnum::TRANSFER_GIVE
  581. ];
  582. }
  583. // 异步处理积分
  584. if ($insert_wallet) {
  585. $res = UserWalletService::batchHandle($insert_wallet);
  586. if (empty($res)) throw new Exception(UserWalletService::getStaticError());
  587. }
  588. // LockHelper::unFLock($key);
  589. $this->success('转送成功');
  590. } catch (\Exception $e) {
  591. // LockHelper::unFLock($key);
  592. return $this->error('赠送失败:' . $e->getMessage());
  593. }
  594. }
  595. }
  596. /**
  597. * 余额转入积分
  598. * @Author: lun
  599. * @DateTime: 2021/11/24 0024 14:58
  600. * @Copyright: copyright (c) 2021 广东七件事集团
  601. * @return mixed|void
  602. * @throws \Exception
  603. */
  604. public function actionTransferScore()
  605. {
  606. if (Yii::$app->request->isPost) {
  607. $form = Yii::$app->request->post();
  608. $rules = [
  609. [['balance'], 'required'],
  610. [['balance'], 'integer'],
  611. [['balance'], 'compare', 'compareValue' => 0, 'operator' => '>'],
  612. [['transaction_password'], 'string'],
  613. ];
  614. $res = Yii::$app->services->validate->validate($form, $rules);
  615. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  616. }
  617. $key = sprintf('TransferScore:%s', $this->user_id);
  618. try {
  619. if (LockHelper::fLock($key, 3)) throw new Exception('请勿频繁请求');
  620. // 获取配置
  621. $config = Yii::$app->services->setting->mall->get($this->mall_id, 'balance');
  622. if (empty($config['is_balance_score'])) throw new Exception('余额转积分功能尚未开启');
  623. if (empty($config['balance_score_ratio'])) throw new Exception('余额转积分功能尚未开启');
  624. $score = BcHelper::floorFloat(($form['balance'] * $config['balance_score_ratio']),2);// 保留两位小数,向下取整
  625. $check_password_result = UserWithdrawLog::checkPassword($this->user_id, $form['transaction_password'], $config);
  626. if(is_array($check_password_result)){
  627. throw new Exception($check_password_result['msg']);
  628. }
  629. // 查询用户余额
  630. $user_wallet = UserWallet::find()->select('id,balance')->where(['mall_id'=>$this->mall_id,'user_id'=>$this->user_id,'status'=>StatusEnum::ENABLED])->asArray()->one();
  631. if (empty($user_wallet) || ($user_wallet['balance'] < $form['balance'])) throw new Exception('余额额度不足');
  632. //扣余额
  633. $insert_wallet[] = [
  634. 'mall_id' => $this->mall_id,
  635. 'user_id' => $this->user_id,
  636. 'is_frozen' => false,
  637. 'wallet_type' => UserWalletService::WALLET_TYPE_BALANCE,
  638. 'money' => -$form['balance'],
  639. 'desc' => '余额转入积分',
  640. 'source_table' => UserWallet::tableName(),
  641. 'source_table_id' => $user_wallet['id'],
  642. 'from_type' => UserWalletEnum::TRANSFER,
  643. 'capital_type'=> UserWalletEnum::TRANSFER_SCORE
  644. ];
  645. //加积分
  646. $insert_wallet[] = [
  647. 'mall_id' => $this->mall_id,
  648. 'user_id' => $this->user_id,
  649. 'is_frozen' => false,
  650. 'wallet_type' => UserWalletService::WALLET_TYPE_SCORE,
  651. 'money' => $score,
  652. 'desc' => '余额转入积分',
  653. 'source_table' => UserWallet::tableName(),
  654. 'source_table_id' => $user_wallet['id'],
  655. 'from_type' => UserWalletEnum::RECHARGE,
  656. 'capital_type'=> UserWalletEnum::RECHARGE_BALANCE
  657. ];
  658. // 异步处理积分
  659. if ($insert_wallet) {
  660. $res = UserWalletService::batchHandle($insert_wallet);
  661. if (empty($res)) throw new Exception(UserWalletService::getStaticError());
  662. }
  663. // LockHelper::unFLock($key);
  664. $this->success('转入成功');
  665. } catch (\Exception $e) {
  666. // LockHelper::unFLock($key);
  667. return $this->error('转积分失败:' . $e->getMessage());
  668. }
  669. }
  670. //获取上一次提现的账号信息
  671. public function actionGetPrevInfo()
  672. {
  673. $request = Yii::$app->request;
  674. if ($request->isGet) {
  675. try {
  676. $get = $request->get();
  677. $res = Yii::$app->services->validate->validate($get, [
  678. // [['from'], 'integer'],
  679. [['type', 'source'], 'string'],
  680. [['from'], 'safe']
  681. ]);
  682. if (!$res) throw new Exception(Yii::$app->services->validate->getErrorMessage());
  683. $info = (new UserWalletService())->getPrevInfo($this->mall_id, $this->user_id, $get);
  684. return $this->success('获取成功', $info);
  685. } catch (\Exception $e) {
  686. return $this->error($e->getMessage());
  687. }
  688. }
  689. }
  690. }