| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- <?php
- namespace common\models\forms;
- use common\helpers\Cache;
- use common\helpers\Date;
- use common\components\Model;
- use common\helpers\Form;
- use common\helpers\snowflake\SnowFake;
- use common\helpers\Tool;
- use common\helpers\user\Balance;
- use common\helpers\user\Cash;
- use common\helpers\user\Info;
- use common\libs\logging\operate\UserOperate;
- use common\models\Article;
- use common\models\ArticleCategory;
- use common\models\DealType;
- use common\models\DecOrder;
- use common\models\Order;
- use common\models\PerfPeriod;
- use common\models\Period;
- use common\models\Transfer;
- use common\models\User;
- use common\models\UserBind;
- use common\models\UserBonus;
- use common\models\UserInfo;
- use common\models\UserRelation;
- use common\models\UserSystem;
- use Yii;
- use yii\base\Exception;
- use yii\helpers\Json;
- /**
- * Login form
- */
- class TransferForm extends Model {
- const allowTransferType = [1, 2, 3];
- const BONUS_TO_BALANCE = 1;
- const BONUS_TO_BONUS = 2;
- const BALANCE_TO_BALANCE = 3;
- public $toUserName;
- public $toRealName;
- public $amount;
- public $payPassword;
- public $type;
- public $remark;
- public $transferCode;
- private $_fromUserInfo;
- private $_toUserInfo;
- private $_transferProp;
- private $_transferConfig;
- private $_fee = 0;
- public function init() {
- parent::init();
- $this->userOperateLogger = new UserOperate([
- 'fetchClass' => Transfer::class,
- ]);
- }
- /**
- * @inheritdoc
- */
- public function rules() {
- return [
- [['toUserName', 'toRealName', 'amount', 'type', 'remark'], 'trim'],
- [['toUserName', 'toRealName', 'amount', 'type', 'payPassword', 'transferCode'], 'required'],
- [['toUserName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME'],
- [['type'], 'isType'],
- [['toUserName'], 'initUser'],
- [['amount'], 'price'],
- [['amount'], 'isAmount'],
- [['transferCode'], 'validateCode'],
- [['payPassword'], 'validatePassword'],
- ];
- }
- /**
- * 指定校验场景
- * @return array
- */
- public function scenarios() {
- $parentScenarios = parent::scenarios();
- $customScenarios = [
- 'transfer' => ['type', 'toUserName', 'toRealName', 'amount', 'remark', 'payPassword', 'transferCode'],
- ];
- return array_merge($parentScenarios, $customScenarios);
- }
- public function attributeLabels() {
- return [
- 'toUserName' => 'Transferred Member Code', // 转入会员编号
- 'amount' => 'Amount', // 金额
- 'payPassword' => 'Payment Password', // 支付密码
- 'transferCode' => 'Verification Code', // 转账校验码
- ];
- }
- /**
- * 初始化转入转出用户信息
- * @param $attribute
- * @return null
- * @throws Exception
- */
- public function initUser($attribute) {
- // 转账记录
- if(!$toUserId = Info::getUserIdByUserName($this->toUserName)){
- $this->addError($attribute, 'Transferred member not exists'); // 转入会员不存在
- return null;
- }
- // if(Info::getUserRealNameByUserId($toUserId)!=$this->toRealName){
- // $this->addError($attribute, '转入会员会员姓名不正确');
- // return null;
- // }
- $this->_toUserInfo = Info::baseInfo($toUserId);
- $fromUserId = \Yii::$app->user->id;
- $fromUser = Info::baseInfo($fromUserId);
- if (!$fromUser) {
- $this->addError($attribute, 'Transferred member not exists'); // 转入会员不存在
- return null;
- }
- // 不能跨国转账
- $fromCountryId = User::getEnCodeInfo($fromUserId)['COUNTRY_ID'];
- $toCountryId = User::getEnCodeInfo($toUserId)['COUNTRY_ID'];
- if ($fromCountryId != $toCountryId) {
- $this->addError($attribute, Yii::t('app', 'transferMemberDoesNotSame'));
- return null;
- }
- // 转账条件判断
- $orderAmount = Order::find()->where('USER_ID=:USER_ID', [':USER_ID' => $fromUserId])->SUM('ORDER_AMOUNT');
- $recNum = intval(DecOrder::find()->where('REC_USER_ID=:REC_USER_ID', [':REC_USER_ID' => $fromUserId])->count());
- //$recNum = UserRelation::firstFloorChildNum($fromUserId);
- // if ($orderAmount < 300 && $recNum==0) {
- // $this->addError($attribute, '消费未满300元或未推荐新人,暂不能转账');
- // return null;
- // }
- $this->_fromUserInfo = $fromUser;
- //是否同体系转账
- // if($this->_transferConfig['isSystem']==1){
- // if($this->_toUserInfo['SYSTEM_ID']!=$this->_fromUserInfo['SYSTEM_ID']){
- // $this->addError($attribute, '只能同一体系间转账');
- // return null;
- // }
- // }
- //是否点位绑定转账
- // if ($this->_transferConfig['isBind'] == 1) {
- // if (!UserBind::sameBind($this->_toUserInfo['ID'], $this->_fromUserInfo['ID'])) {
- // $this->addError($attribute, '只能点位绑定在一起的会员之间转账');
- // return null;
- // }
- // }
- //奖金转奖金限同一身份证
- /*if ($this->type == self::BONUS_TO_BONUS) {
- $toIdCard = User::findOneAsArray('ID=:ID', [':ID' => $toUser['USER_ID']], 'ID_CARD');
- $fromIdCard = User::findOneAsArray('ID=:ID', [':ID' => $fromUser['USER_ID']], 'ID_CARD');
- if ($toIdCard['ID_CARD'] && ($toIdCard['ID_CARD'] != $fromIdCard['ID_CARD'])) {
- $this->addError($attribute, '奖金转奖金只能在同一身份证下进行');
- return null;
- }
- }*/
- //奖金转现金限一周一次
- /*if ($this->type == self::BONUS_TO_BALANCE) {
- if (Transfer::hasThisWeekTransfer(\Yii::$app->user->id)) {
- $this->addError($attribute, '转账失败,每周只可以转账一次');
- return null;
- }
- }*/
- }
- /**
- * 校验申请金额是否小于当前余额并符合配置中的设置
- * @param $attribute
- * @return null
- */
- public function isAmount($attribute) {
- if(!$this->_fromUserInfo){
- $this->addError($attribute, 'Member info has not been verified'); // 会员信息未验证通过
- return null;
- }
- if ($this->amount <= 0) {
- $this->addError($attribute, 'The transfer amount must be greater than 0'); // 转账金额必须大于0
- }
- if ((int)$this->amount!=$this->amount) {
- $this->addError('scenario', 'The transfer amount must be a round number'); // 转账金额必须是整数
- }
- $minAmount = $this->_transferConfig['outMin'];
- if ($this->amount < $minAmount) {
- $this->addError($attribute, 'The transfer amount is lower than the transfer limit'); // 转账金额低于转账下限
- }
- $maxAmount = $this->_transferConfig['outMax'];
- if ($maxAmount && $this->amount > $maxAmount) {
- $this->addError($attribute, 'The transfer amount is higher than the transfer limit'); // 转账金额高于转账上限
- }
- //周转账上限
- if($this->_transferConfig['weekMax']!=0){
- if($this->amount+Transfer::weekTransfer($this->_fromUserInfo['ID'])>$this->_transferConfig['weekMax']){
- $this->addError($attribute, 'The working book limit is exceeded'); // 超出周转账上限
- }
- }
- //月转账上限
- if($this->_transferConfig['monthMax']!=0){
- if($this->amount+Transfer::monthTransfer($this->_fromUserInfo['ID'])>$this->_transferConfig['weekMax']){
- $this->addError($attribute, 'Exceed the monthly transfer limit'); // 超出月转账上限
- }
- }
- // 获取当前用户的可用金额
- if( $this->type == self::BALANCE_TO_BALANCE ) {
- $haveBalance = Cash::getAvailableBalance($this->_fromUserInfo['ID']);
- }else {
- $haveBalance = Balance::getAvailableBalance($this->_fromUserInfo['ID']);
- }
- if ($this->amount > $haveBalance) {
- $this->addError($attribute, 'The transfer amount must be less than your available balance'); // 转账金额必须小于自己的可用余额
- }
- // 转账比例
- if ($this->type == self::BONUS_TO_BALANCE) {
- $isCanTransferProp = Cache::getSystemConfig()['isCanTransferProp']['VALUE'];
- if ($isCanTransferProp == 1) {
- $maxAmount = Tool::formatPrice($this->_fromUserInfo['TRANSFER_PROP'] * Balance::getAvailableBalance($this->_fromUserInfo['ID']) * 0.01);
- if ($this->amount > $maxAmount) {
- $this->addError($attribute, 'The transfer amount exceeds the transfer ratio limit'); // 转账金额超出转账比例限额
- }
- }
- }
- //手续费
- if($this->_transferConfig['fee']!=0){
- $fee = Tool::formatPrice($this->amount * ($this->_transferConfig['fee']) * 0.01);
- if($this->_transferConfig['feeMin']!=0&&$fee<$this->_transferConfig['feeMin']){
- $fee = $this->_transferConfig['feeMin'];
- }
- if($this->_transferConfig['feeMax']!=0&&$fee>$this->_transferConfig['feeMax']){
- $fee = $this->_transferConfig['feeMax'];
- }
- $this->_fee = $fee;
- }
- }
- /**
- * 转账类型判断
- * @param $attribute
- */
- public function isType($attribute) {
- if (!in_array($this->type, self::allowTransferType)) {
- $this->addError($attribute, 'Types of transfers that are not allowed'); // 不允许的转账类型
- }
- //获取转账参数
- if(!$this->_transferConfig = Json::decode(Cache::getSystemConfig()['allowWallet']['VALUE'])[$this->type-1]){
- $this->addError($attribute, 'Wrong type of transfer'); // 错误的转账类型
- }
- if(!$this->_transferConfig['isOpen']){
- $this->addError($attribute, 'Type of transfer that is not available'); // 不可用的转账类型
- }
- }
- /**
- * 校验支付密码
- * @param $attribute
- * @param $params
- */
- public function validatePassword($attribute, $params) {
- if (!User::validatePayPassword($this->_fromUserInfo['ID'], $this->payPassword)) {
- $this->addError($attribute, 'The payment password is incorrect');//支付密码不正确
- }
- }
- public function validateCode($attribute, $params) {
- $uid = \Yii::$app->user->id;
- $redisCode = \Yii::$app->redis->getset('transferCode_'.$uid,'');
- \Yii::$app->redis->del('transferCode_'.$uid);
- if ($this->transferCode!=$redisCode) {
- $this->addError($attribute, 'Transfer verification failed '.$redisCode); // 转账校验失败
- }
- }
- /**
- * 生成随机数
- * @param $length
- * @param int $numeric
- * @return string
- */
- public function random($length, $numeric = 0) {
- $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
- $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
- $hash = '';
- $max = strlen($seed) - 1;
- for ($i = 0; $i < $length; $i++) {
- $hash .= $seed[mt_rand(0, $max)];
- }
- return $hash;
- }
- /**
- * 转账
- * @return Transfer|null
- * @throws \Exception
- */
- public function transfer() {
- if (!$this->validate()) {
- return null;
- }
- if ($this->_fromUserInfo['ID']==$this->_toUserInfo['ID']){
- throw new \Exception(Yii::t('app', 'notAllowedToTransferToYourself'));
- }
- $fromData = Balance::getLogData($this->_fromUserInfo['ID']);
- $toData = Balance::getLogData($this->_toUserInfo['ID']);
- $this->userOperateLogger->saveBeforeContent=array_merge($fromData,$toData);
- $db = \Yii::$app->db;
- $transaction = $db->beginTransaction();
- try {
- $amount = Tool::formatPrice($this->amount - $this->_fee);
- // 转账记录
- $period = Period::instance();
- $model = new Transfer();
- $model->ID = SnowFake::instance()->generateId();
- $model->TRANSFER_SN = Transfer::generateSN();
- $model->OUT_UID = $this->_fromUserInfo['ID'];
- $model->LAST_OUT_USER_NAME = $this->_fromUserInfo['USER_NAME'];
- $model->LAST_OUT_REAL_NAME = $this->_fromUserInfo['REAL_NAME'];
- $model->LAST_OUT_DEC_LV = $this->_fromUserInfo['DEC_LV'];
- $model->LAST_OUT_DEC_ROLE_ID = $this->_fromUserInfo['DEC_ROLE_ID'];
- $model->OUT_WALLET = $this->_transferConfig['out'];
- $model->LAST_OUT_SYSTEM_ID = $this->_fromUserInfo['SYSTEM_ID'] ? $this->_fromUserInfo['SYSTEM_ID'] : '';
- $model->IN_UID = $this->_toUserInfo['ID'];
- $model->LAST_IN_USER_NAME = $this->_toUserInfo['USER_NAME'];
- $model->LAST_IN_REAL_NAME = $this->_toUserInfo['REAL_NAME'];
- $model->LAST_IN_DEC_LV = $this->_toUserInfo['DEC_LV'];
- $model->IN_WALLET = $this->_transferConfig['in'];
- $model->LAST_IN_SYSTEM_ID = $this->_toUserInfo['SYSTEM_ID'] ? $this->_toUserInfo['SYSTEM_ID'] : '';
- $model->ORI_AMOUNT = $this->amount;
- $model->FEE = $this->_fee;
- $model->AMOUNT = $amount;
- $model->REMARK = $this->remark;
- $model->PERIOD_NUM = $period->getNowPeriodNum();
- $model->CALC_MONTH = $period->getNowYearMonth();
- $model->CREATED_AT = Date::nowTime();
- if (!$model->save()) {
- throw new Exception(Form::formatErrorsForApi($model->getErrors()));
- }
- if ($this->type == self::BONUS_TO_BALANCE) {
- // 会员金额减少
- Balance::changeUserBonus($this->_fromUserInfo['ID'], 'bonus', -abs($this->amount), ['TRANSFER_SN' => $model->TRANSFER_SN, 'DEAL_TYPE_ID' => DealType::TRANSFER_OUT, 'REMARK' => 'To:' . $this->_toUserInfo['USER_NAME'] . ',' . $this->remark]);
- Cash::changeUserCash($this->_toUserInfo['ID'], 'CASH', abs($amount), ['TRANSFER_SN' => $model->TRANSFER_SN,'DEAL_TYPE_ID' => DealType::TRANSFER_IN, 'REMARK' => 'From:' . $this->_fromUserInfo['USER_NAME'] . ',' . $this->remark]);
- } elseif($this->type == self::BONUS_TO_BONUS) {
- // 会员金额减少
- Balance::changeUserBonus($this->_fromUserInfo['ID'], 'bonus', -abs($this->amount), ['TRANSFER_SN' => $model->TRANSFER_SN, 'DEAL_TYPE_ID' => DealType::TRANSFER_OUT, 'REMARK' => 'To:' . $this->_toUserInfo['USER_NAME'] . ',' . $this->remark]);
- Balance::changeUserBonus($this->_toUserInfo['ID'], 'bonus', abs($amount), ['TRANSFER_SN' => $model->TRANSFER_SN, 'DEAL_TYPE_ID' => DealType::TRANSFER_IN, 'REMARK' => 'From:' . $this->_fromUserInfo['USER_NAME'] . ',' . $this->remark]);
- }else if ($this->type == self::BALANCE_TO_BALANCE) {
- // 会员金额减少
- Cash::changeUserCash($this->_fromUserInfo['ID'], 'CASH', -abs($this->amount), ['TRANSFER_SN' => $model->TRANSFER_SN,'DEAL_TYPE_ID' => DealType::TRANSFER_OUT, 'REMARK' => 'To:' . $this->_toUserInfo['USER_NAME'] . ',' . $this->remark]);
- Cash::changeUserCash($this->_toUserInfo['ID'], 'CASH', abs($amount), ['TRANSFER_SN' => $model->TRANSFER_SN,'DEAL_TYPE_ID' => DealType::TRANSFER_IN, 'REMARK' => 'From:' . $this->_fromUserInfo['USER_NAME'] . ',' . $this->remark]);
- }else {
- throw new \Exception(Yii::t('app', 'wrongTransactionType'));
- }
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollBack();
- $this->addError('edit', $e->getMessage());
- return null;
- }
- $fromData = Balance::getLogData($this->_fromUserInfo['ID']);
- $toData = Balance::getLogData($this->_toUserInfo['ID']);
- $this->userOperateLogger->saveAfterContent=array_merge($fromData,$toData);
- unset($fromData,$toData);
- $this->userOperateLogger->clean()->save([
- 'optType' => '会员转账',
- 'userId' => \Yii::$app->user->id,
- 'userName' => Info::getUserNameByUserId(\Yii::$app->user->id),
- 'remark' => $this->remark,
- ]);
- return $model;
- }
- }
|