mall_id, 'digital'); if (!$setting || !$setting['is_enable']) return $this->error('系统未开启'); return $action; } /** * * 不用进行登录验证的方法 * * 例如: ['index', 'update', 'create', 'view', 'delete'] * 默认全部需要验证 * * @var array */ protected $authOptional = []; /** * 获取用户基本信息 * @return array|mixed */ public function actionUserInfo() { try { $setting = MallSetting::conf($this->mall_id, 'digital'); $user_digital = UserDigital::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]); $return['digital'] = $user_digital->digital ?? 0; //获取设置 $return['enable_transfer'] = $setting['is_transfer'] ?? 0; $return['enable_to_balance'] = $setting['enable_to_balance'] ?? 0; $return['enable_to_score'] = $setting['enable_to_score'] ?? 0; $return['name'] = $setting['name'] ?? '数字币'; $return['forwarding_charge'] = $setting['forwarding_charge'] ?? 0; //转送手续费 $return['forwarding_charge'] = $return['forwarding_charge'] . '%'; $return['to_balance_ratio'] = $setting['to_balance_ratio'] ?? 0; //数字币转余额比例 $return['to_score_ratio'] = $setting['to_score_ratio'] ?? 0; //数字币转余额比例 return $this->success(ApiCode::CODE_SUCCESS_TITLE, $return); } catch (\Exception $e) { return $this->error($e->getMessage()); } } /** * 数字币列表 */ public function actionUserList() { try { $params = Yii::$app->request->get(); $res = Yii::$app->services->validate->validate($params, [ [['status'], 'safe'], ]); if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage()); $status = $params['status'] == 1 ? DigitalLog::SEND_STATUS_NORMAL : DigitalLog::SEND_STATUS_FROZEN; $where[] = ['in', 'status', [StatusEnum::DISABLED, StatusEnum::ENABLED]]; $where[] = ['mall_id' => $this->mall_id]; $where[] = ['user_id' => $this->user_id]; $where[] = ['send_status' => $status]; $params['select'] = 'id,change_type,change_num,desc,from_type,capital_type,created_at,order_no'; $params['order'] = 'id desc'; $params['where'] = $where; $page_data = DigitalLog::listPage($params, false); $commission_map = GlobalVarMap::getEnumMapByType('FromTypeMap'); $capital_type_map = GlobalVarMap::getEnumMapByType('CapitalTypeMap'); foreach ($page_data['list'] as $key => $val) { $val['source_text'] = ($commission_map[$val['from_type']] ?? '') . ($capital_type_map[$val['capital_type']] ? '-' . $capital_type_map[$val['capital_type']] : ''); $val['created_at'] = date('Y-m-d H:i:s', $val['created_at']); $page_data['list'][$key] = $val; } return $this->success(ApiCode::CODE_SUCCESS_TITLE, $page_data); } catch (\Exception $e) { return $this->error($e->getMessage()); } } /** * 转送 */ public function actionTransfer() { if (Yii::$app->request->isPost) { $lock_key = 'digital_transfer_' . $this->user_id; $identification = uniqid(); $t = \Yii::$app->db->beginTransaction(); if (!LockHelper::lock($lock_key, $identification, 30, 5)) return $this->error('操作太频繁'); try { $params = Yii::$app->request->post(); $res = Yii::$app->services->validate->validate($params, [ [['num', 'user_id'], 'required'], [['num', 'user_id'], 'integer'], [['num'], 'compare', 'compareValue' => 0, 'operator' => '>'] ]); if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage()); $setting = MallSetting::conf($this->mall_id, 'digital'); if (!$setting['is_transfer']) throw new \Exception('系统未开启转送功能'); if ($params['user_id'] == $this->user_id) throw new Exception('赠送的用户不能是本人哦'); $user_digital = UserDigital::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]); if (!$user_digital || $user_digital->digital < $params['num']) throw new \Exception('超出可转数量'); $forwarding_charge_radio = $setting['forwarding_charge'] ?? 0; $forwarding_charge = bcmul($params['num'], $forwarding_charge_radio / 100, 2); $need_deduct_digital = bcadd($params['num'], $forwarding_charge, 2); if ($user_digital->digital < $need_deduct_digital) throw new \Exception('超出可转数量'); // 检查用户是否存在 $receive_user = User::getUser([['id' => $params['user_id'], 'mall_id' => $this->mall_id]], 'id'); if (empty($receive_user)) throw new Exception('赠送的用户不存在'); //开启事务 $setting = MallSetting::conf($this->mall_id, 'digital'); $digital_name = $setting['name'] ?? '数字币'; $send_data = [ 'desc' => '用户id: ' . $user_digital['user_id'] . '向用户id: ' . $params['user_id'] . '转送' . $params['num'] . $digital_name, 'source_table' => User::tableName(), 'source_table_id' => $params['user_id'], 'from_type' => UserWalletEnum::TRANSFER, 'capital_type' => UserWalletEnum::TRANSFER_GIVE, 'contributor_id' => $user_digital['user_id'], 'contributor_money' => $forwarding_charge, //手续费 'contributor_name' => '转送' ]; $res = UserDigital::handleUserDigital($this->mall_id, $user_digital['user_id'], $need_deduct_digital * -1, false, $send_data); if ($res === false) throw new \Exception(UserDigital::getStaticError()); $receive_data = [ 'desc' => '用户id: ' . $user_digital['user_id'] . '向用户id: ' . $params['user_id'] . '转送' . $params['num'] . $digital_name, 'source_table' => User::tableName(), 'source_table_id' => $user_digital['user_id'], 'from_type' => UserWalletEnum::TRANSFER, 'capital_type' => UserWalletEnum::TRANSFER_GIVE, 'contributor_id' => $user_digital['user_id'], 'contributor_name' => '转送' ]; $res = UserDigital::handleUserDigital($this->mall_id, $params['user_id'], $params['num'], false, $receive_data); if ($res === false) throw new \Exception(UserDigital::getStaticError()); $t->commit(); LockHelper::uLock($lock_key, $identification); return $this->success('转送成功'); } catch (\Exception $e) { $t->rollBack(); LockHelper::uLock($lock_key, $identification); return $this->error($e->getMessage()); } } } public function actionPreviewConvert() { try { if (!Yii::$app->request->isGet) throw new \Exception('this request method is not supported'); $params = Yii::$app->request->get(); $res = Yii::$app->services->validate->validate($params, [ [['from', 'to'], 'required'], [['from', 'to'], 'string'], ]); if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage()); $setting = MallSetting::conf($this->mall_id, 'digital'); $is_open_switch = 0; $from_text = $setting['name']; $to_text = ''; $from_ratio = 1; $to_ratio = 0; if ($params['from'] == 'digital' && $params['to'] == 'balance') { $is_open_switch = $setting['enable_to_balance'] ?? 0; $to_text = Yii::$app->services->setting->mall->get($this->mall_id, 'balance.balance_name') ?? '余额'; $to_ratio = $setting['to_balance_ratio'] ?? 0; } elseif ($params['from'] == 'digital' && $params['to'] == 'score') { $is_open_switch = $setting['enable_to_score'] ?? 0; $to_text = \Yii::$app->services->setting->mall->get($this->mall_id, 'score.score_name') ?? '积分'; $to_ratio = $setting['to_score_ratio'] ?? 0; } if (empty($is_open_switch)) throw new \Exception('system is not allowed to this action'); if (empty($to_ratio)) throw new \Exception('system is not corrected to set setting'); $user_digital = UserDigital::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]); $currency = $user_digital->digital ?? 0; return $this->success('数据请求成功', compact('currency', 'from_text', 'to_text', 'from_ratio', 'to_ratio')); } catch (\Exception $e) { return $this->error($e->getMessage()); } } public function actionConvert() { if (Yii::$app->request->isPost) { $lock_key = 'digital_convert_' . $this->user_id; $identification = uniqid(); $t = \Yii::$app->db->beginTransaction(); if (!LockHelper::lock($lock_key, $identification, 30, 5)) return $this->error('操作太频繁'); try { $params = Yii::$app->request->post(); $res = Yii::$app->services->validate->validate($params, [ [['num', 'from', 'to'], 'required'], [['num',], 'integer'], [['from', 'to'], 'string'], [['num'], 'compare', 'compareValue' => 0, 'operator' => '>'] ]); if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage()); $setting = MallSetting::conf($this->mall_id, 'digital'); $is_open_switch = 0; $from_text = $setting['name'] ?? '数字币'; $to_text = ''; $from_ratio = 1; $to_ratio = 0; if ($params['from'] == 'digital' && $params['to'] == 'balance') { $is_open_switch = $setting['enable_to_balance'] ?? 0; $to_text = Yii::$app->services->setting->mall->get($this->mall_id, 'balance.balance_name') ?? '余额'; $to_ratio = $setting['to_balance_ratio'] ?? 0; } elseif ($params['from'] == 'digital' && $params['to'] == 'score') { $is_open_switch = $setting['enable_to_score'] ?? 0; $to_text = \Yii::$app->services->setting->mall->get($this->mall_id, 'score.score_name') ?? '积分'; $to_ratio = $setting['to_score_ratio'] ?? 0; } if (empty($is_open_switch)) throw new \Exception('system is not allowed to this action'); if (empty($to_ratio)) throw new \Exception('system is not corrected to set setting'); $user_digital = UserDigital::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]); if (!$user_digital || $user_digital->digital < $params['num']) throw new \Exception("当前{$from_text}不足"); $get_num = bcdiv(bcmul($to_ratio, $params['num'], 2), $from_ratio, 2); $desc = $params['num'] . $from_text . '转为' . $get_num . $to_text; $send_data = [ 'desc' => $desc, 'source_table' => UserDigital::tableName(), 'source_table_id' => $user_digital['id'], 'from_type' => UserWalletEnum::TRANSFER, 'capital_type' => UserWalletEnum::TRANSFER_GIVE ]; $res = UserDigital::handleUserDigital($this->mall_id, $user_digital['user_id'], $params['num'] * -1, false, $send_data); if ($res === false) throw new \Exception(UserDigital::getStaticError()); $handle_wallet = [ 'mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'is_frozen' => false, 'wallet_type' => $params['to'] == 'balance' ? UserWalletService::WALLET_TYPE_BALANCE : UserWalletService::WALLET_TYPE_SCORE, 'money' => $get_num, 'desc' => $desc, 'source_table' => UserDigital::tableName(), 'source_table_id' => $user_digital['id'], 'from_type' => UserWalletEnum::TRANSFER, 'capital_type' => UserWalletEnum::TRANSFER_GIVE ]; $res = UserWalletService::handle(0, $handle_wallet); if (!$res) { $error_msg = UserWalletService::$static_error ?? $to_text . '转换失败'; throw new \Exception($error_msg); } $t->commit(); LockHelper::uLock($lock_key, $identification); return $this->success('转换成功'); } catch (\Exception $e) { $t->rollBack(); LockHelper::uLock($lock_key, $identification); return $this->error($e->getMessage()); } } } }