TransferForm.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. <?php
  2. namespace common\models\forms;
  3. use common\helpers\bonus\CalcCache;
  4. use common\helpers\Cache;
  5. use common\helpers\Date;
  6. use common\components\Model;
  7. use common\helpers\Form;
  8. use common\helpers\LoggerTool;
  9. use common\helpers\snowflake\SnowFake;
  10. use common\helpers\Tool;
  11. use common\helpers\user\Balance;
  12. use common\helpers\user\Cash;
  13. use common\helpers\user\Info;
  14. use common\libs\logging\operate\UserOperate;
  15. use common\models\Article;
  16. use common\models\ArticleCategory;
  17. use common\models\DealType;
  18. use common\models\DecOrder;
  19. use common\models\Order;
  20. use common\models\PerfPeriod;
  21. use common\models\Period;
  22. use common\models\Transfer;
  23. use common\models\User;
  24. use common\models\UserBind;
  25. use common\models\UserBonus;
  26. use common\models\UserInfo;
  27. use common\models\UserRelation;
  28. use common\models\UserSystem;
  29. use frontendApi\modules\v1\models\Relation;
  30. use yii\base\Exception;
  31. use yii\helpers\Json;
  32. /**
  33. * Login form
  34. */
  35. class TransferForm extends Model {
  36. const allowTransferType = [1, 2, 3, 4];
  37. const BONUS_TO_BALANCE = 1;
  38. const BONUS_TO_BONUS = 2;
  39. const BALANCE_TO_BALANCE = 3;
  40. const POINT_TO_BALANCE = 4;
  41. const LOOP_FINISH = 1;
  42. const LOOP_CONTINUE = 2;
  43. private $_periodNum = 0;
  44. public $toUserName;
  45. public $toRealName;
  46. public $amount;
  47. public $payPassword;
  48. public $type;
  49. public $remark;
  50. public $transferCode;
  51. private $_fromUserInfo;
  52. private $_toUserInfo;
  53. private $_transferProp;
  54. private $_transferConfig;
  55. private $_fee = 0;
  56. public function init() {
  57. parent::init();
  58. $this->userOperateLogger = new UserOperate([
  59. 'fetchClass' => Transfer::class,
  60. ]);
  61. }
  62. /**
  63. * @inheritdoc
  64. */
  65. public function rules() {
  66. return [
  67. [['toUserName', 'toRealName', 'amount', 'type', 'remark'], 'trim'],
  68. [['toUserName', 'toRealName', 'amount', 'type', 'payPassword', 'transferCode'], 'required'],
  69. [['toUserName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME'],
  70. [['type'], 'isType'],
  71. [['toUserName'], 'initUser'],
  72. [['amount'], 'price'],
  73. [['amount'], 'isAmount'],
  74. [['transferCode'], 'validateCode'],
  75. [['payPassword'], 'validatePassword'],
  76. ];
  77. }
  78. /**
  79. * 指定校验场景
  80. * @return array
  81. */
  82. public function scenarios() {
  83. $parentScenarios = parent::scenarios();
  84. $customScenarios = [
  85. 'transfer' => ['type', 'toUserName', 'toRealName', 'amount', 'remark', 'payPassword', 'transferCode'],
  86. ];
  87. return array_merge($parentScenarios, $customScenarios);
  88. }
  89. public function attributeLabels() {
  90. return [
  91. 'toUserName' => '转入会员编号',
  92. 'amount' => '金额',
  93. 'payPassword' => '支付密码',
  94. 'transferCode' => '转账校验码',
  95. ];
  96. }
  97. /**
  98. * 初始化转入转出用户信息
  99. * @param $attribute
  100. * @return null
  101. * @throws Exception
  102. * @throws \Exception
  103. */
  104. public function initUser($attribute) {
  105. // 转账记录
  106. if(!$toUserId = Info::getUserIdByUserName($this->toUserName)){
  107. $this->addError($attribute, '转入会员不存在');
  108. return null;
  109. }
  110. // if(Info::getUserRealNameByUserId($toUserId)!=$this->toRealName){
  111. // $this->addError($attribute, '转入会员会员姓名不正确');
  112. // return null;
  113. // }
  114. $this->_toUserInfo = Info::baseInfo($toUserId);
  115. $fromUserId = \Yii::$app->user->id;
  116. $fromUser = Info::baseInfo($fromUserId);
  117. if (!$fromUser) {
  118. $this->addError($attribute, '转出会员不存在');
  119. return null;
  120. }
  121. // 转账是否已开启
  122. $transferSwitch = Cache::getSystemConfig()['transferSwitch']['VALUE'] ?? '';
  123. if ($transferSwitch != 1) {
  124. // 转账未开启,判断是否报单中心. 报单中心可开启转账
  125. $isDec = \frontendApi\modules\v1\models\User::getEnCodeInfo($fromUserId)['IS_DEC'];
  126. if ($isDec != 1) {
  127. throw new \Exception('转账功能已关闭');
  128. return null;
  129. }
  130. }
  131. // 转账条件判断
  132. // $orderAmount = Order::find()->where('USER_ID=:USER_ID', [':USER_ID' => $fromUserId])->SUM('ORDER_AMOUNT');
  133. // $recNum = intval(DecOrder::find()->where('REC_USER_ID=:REC_USER_ID', [':REC_USER_ID' => $fromUserId])->count());
  134. //$recNum = UserRelation::firstFloorChildNum($fromUserId);
  135. // if ($orderAmount < 300 && $recNum==0) {
  136. // $this->addError($attribute, '消费未满300元或未推荐新人,暂不能转账');
  137. // return null;
  138. // }
  139. $this->_fromUserInfo = $fromUser;
  140. //是否同体系转账
  141. // if($this->_transferConfig['isSystem']==1){
  142. // if($this->_toUserInfo['SYSTEM_ID']!=$this->_fromUserInfo['SYSTEM_ID']){
  143. // $this->addError($attribute, '只能同一体系间转账');
  144. // return null;
  145. // }
  146. // }
  147. //是否点位绑定转账
  148. // if ($this->_transferConfig['isBind'] == 1) {
  149. // if (!UserBind::sameBind($this->_toUserInfo['ID'], $this->_fromUserInfo['ID'])) {
  150. // $this->addError($attribute, '只能点位绑定在一起的会员之间转账');
  151. // return null;
  152. // }
  153. // }
  154. //奖金转奖金限同一身份证
  155. /*if ($this->type == self::BONUS_TO_BONUS) {
  156. $toIdCard = User::findOneAsArray('ID=:ID', [':ID' => $toUser['USER_ID']], 'ID_CARD');
  157. $fromIdCard = User::findOneAsArray('ID=:ID', [':ID' => $fromUser['USER_ID']], 'ID_CARD');
  158. if ($toIdCard['ID_CARD'] && ($toIdCard['ID_CARD'] != $fromIdCard['ID_CARD'])) {
  159. $this->addError($attribute, '奖金转奖金只能在同一身份证下进行');
  160. return null;
  161. }
  162. }*/
  163. //奖金转现金限一周一次
  164. /*if ($this->type == self::BONUS_TO_BALANCE) {
  165. if (Transfer::hasThisWeekTransfer(\Yii::$app->user->id)) {
  166. $this->addError($attribute, '转账失败,每周只可以转账一次');
  167. return null;
  168. }
  169. }*/
  170. // 转账网络限制
  171. // 期数
  172. $this->_periodNum = Period::instance()->getNowPeriodNum();
  173. // 发起人
  174. $initiator = Info::getBaseUserByUserName($fromUser['USER_NAME']);
  175. // 发起人是否报单中心
  176. $initiatorIsDec = $initiator['IS_DEC'] == 1;
  177. // 接受者
  178. $recipient = Info::getBaseUserByUserName($this->toUserName);
  179. // 发起人是否报单中心
  180. $recipientIsDec = $recipient['IS_DEC'] == 1;
  181. // 1. 如果发起人和接受者都是报单中心,则转账无限制
  182. if (($initiatorIsDec == 1) && ($recipientIsDec == 1)) {
  183. return true;
  184. }
  185. // 2. 如果发起人是报单中心, 则可以转账给自己的推荐网下级
  186. if ($initiatorIsDec == 1) {
  187. $sql = <<<SQL
  188. WITH recursive t_rec AS
  189. (
  190. SELECT
  191. m.USER_ID,
  192. U.USER_NAME,
  193. m.PARENT_UID,
  194. U2.USER_NAME AS PARENT_NAME,
  195. 1 AS node_level
  196. FROM
  197. AR_USER_RELATION_NEW m
  198. LEFT JOIN AR_USER U ON U.ID = m.USER_ID
  199. LEFT JOIN AR_USER U2 ON U2.ID = m.PARENT_UID
  200. WHERE
  201. U.USER_NAME = :USER_NAME
  202. UNION ALL
  203. SELECT
  204. t1.USER_ID,
  205. U.USER_NAME,
  206. t1.PARENT_UID,
  207. U2.USER_NAME AS PARENT_NAME,
  208. t2.node_level + 1 -- 结点层级
  209. FROM
  210. AR_USER_RELATION_NEW t1
  211. JOIN t_rec t2 ON t2.PARENT_UID = t1.USER_ID
  212. LEFT JOIN AR_USER U ON U.ID = t1.USER_ID
  213. LEFT JOIN AR_USER U2 ON U2.ID = t1.PARENT_UID
  214. )
  215. SELECT
  216. *
  217. FROM
  218. t_rec
  219. SQL;
  220. // 查询接受者的所有上级,如果没有发起人,则不能转账
  221. $relationNode = \Yii::$app->db->createCommand($sql)
  222. ->bindValue(':USER_NAME', $this->toUserName)
  223. ->queryAll();
  224. $relationNode = array_column($relationNode, 'USER_NAME');
  225. if (!in_array($fromUser['USER_NAME'], $relationNode)) {
  226. $this->addError($attribute, '转账失败:转入会员不是您的下级');
  227. return null;
  228. }
  229. return true;
  230. }
  231. // 3. 如果发起人是普通会员,则只能转给自己推荐网的某个节点
  232. // 上级节点
  233. $sqlUp =<<<SQL
  234. WITH recursive t_rec AS
  235. (
  236. SELECT
  237. m.USER_ID,
  238. U.USER_NAME,
  239. m.PARENT_UID,
  240. U2.USER_NAME AS PARENT_NAME,
  241. 1 AS node_level
  242. FROM
  243. AR_USER_RELATION_NEW m
  244. LEFT JOIN AR_USER U ON U.ID = m.USER_ID
  245. LEFT JOIN AR_USER U2 ON U2.ID = m.PARENT_UID
  246. WHERE
  247. U.USER_NAME = :USER_NAME
  248. UNION ALL
  249. SELECT
  250. t1.USER_ID,
  251. U.USER_NAME,
  252. t1.PARENT_UID,
  253. U2.USER_NAME AS PARENT_NAME,
  254. t2.node_level + 1 -- 结点层级
  255. FROM
  256. AR_USER_RELATION_NEW t1
  257. JOIN t_rec t2 ON t2.PARENT_UID = t1.USER_ID
  258. LEFT JOIN AR_USER U ON U.ID = t1.USER_ID
  259. LEFT JOIN AR_USER U2 ON U2.ID = t1.PARENT_UID
  260. )
  261. SELECT
  262. *
  263. FROM
  264. t_rec
  265. SQL;
  266. // 上级
  267. $relationNodeUp = \Yii::$app->db->createCommand($sqlUp)
  268. ->bindValue(':USER_NAME' , $fromUser['USER_NAME'])
  269. ->queryAll();
  270. $relationNodeUp = array_column($relationNodeUp, 'USER_NAME');
  271. unset($relationNodeUp[$fromUser['USER_NAME']]);
  272. if (!in_array($this->toUserName, $relationNodeUp)) {
  273. // 下级节点
  274. $sqlFloor =<<<SQL
  275. WITH recursive t_rec AS
  276. (
  277. SELECT
  278. m.USER_ID,
  279. U.USER_NAME,
  280. m.PARENT_UID,
  281. U2.USER_NAME AS PARENT_NAME,
  282. 1 AS node_level
  283. FROM
  284. AR_USER_RELATION_NEW m
  285. LEFT JOIN AR_USER U ON U.ID = m.USER_ID
  286. LEFT JOIN AR_USER U2 ON U2.ID = m.PARENT_UID
  287. WHERE
  288. U.USER_NAME = :USER_NAME
  289. UNION ALL
  290. SELECT
  291. t1.USER_ID,
  292. U.USER_NAME,
  293. t1.PARENT_UID,
  294. U2.USER_NAME AS PARENT_NAME,
  295. t2.node_level + 1 -- 结点层级
  296. FROM
  297. AR_USER_RELATION_NEW t1
  298. JOIN t_rec t2 ON t2.PARENT_UID = t1.USER_ID
  299. LEFT JOIN AR_USER U ON U.ID = t1.USER_ID
  300. LEFT JOIN AR_USER U2 ON U2.ID = t1.PARENT_UID
  301. )
  302. SELECT
  303. *
  304. FROM
  305. t_rec
  306. SQL;
  307. // 下级
  308. $relationNodeFloor = \Yii::$app->db->createCommand($sqlFloor)
  309. ->bindValue(':USER_NAME' , $this->toUserName)
  310. ->queryAll();
  311. $relationNodeFloor = array_column($relationNodeFloor, 'USER_NAME');
  312. if (!in_array($fromUser['USER_NAME'], $relationNodeFloor)) {
  313. $this->addError($attribute, '转账失败:转入会员不是您的上级');
  314. return null;
  315. }
  316. }
  317. return true;
  318. }
  319. /**
  320. * 校验申请金额是否小于当前余额并符合配置中的设置
  321. * @param $attribute
  322. * @return null
  323. */
  324. public function isAmount($attribute) {
  325. if(!$this->_fromUserInfo){
  326. $this->addError($attribute, '会员信息未验证通过');
  327. return null;
  328. }
  329. if ($this->amount <= 0) {
  330. $this->addError($attribute, '转账金额必须大于0');
  331. }
  332. if ((int)$this->amount!=$this->amount) {
  333. $this->addError('scenario', '转账金额必须是整数');
  334. }
  335. $minAmount = $this->_transferConfig['outMin'];
  336. if ($this->amount < $minAmount) {
  337. $this->addError($attribute, '转账金额低于转账下限');
  338. }
  339. $maxAmount = $this->_transferConfig['outMax'];
  340. if ($maxAmount && $this->amount > $maxAmount) {
  341. $this->addError($attribute, '转账金额高于转账上限');
  342. }
  343. //周转账上限
  344. if($this->_transferConfig['weekMax']!=0){
  345. if($this->amount+Transfer::weekTransfer($this->_fromUserInfo['ID'])>$this->_transferConfig['weekMax']){
  346. $this->addError($attribute, '超出周转账上限');
  347. }
  348. }
  349. //月转账上限
  350. if($this->_transferConfig['monthMax']!=0){
  351. if($this->amount+Transfer::monthTransfer($this->_fromUserInfo['ID'])>$this->_transferConfig['weekMax']){
  352. $this->addError($attribute, '超出月转账上限');
  353. }
  354. }
  355. // 获取当前用户的可用金额
  356. if( $this->type == self::BALANCE_TO_BALANCE ) {
  357. $haveBalance = Cash::getAvailableBalance($this->_fromUserInfo['ID']);
  358. }else if ($this->type == self::POINT_TO_BALANCE) {
  359. $haveBalance = Balance::getBalanceReconsumePoints($this->_fromUserInfo['ID']);
  360. } else {
  361. $haveBalance = Balance::getAvailableBalance($this->_fromUserInfo['ID']);
  362. }
  363. if ($this->amount > $haveBalance) {
  364. $this->addError($attribute, '转账金额必须小于自己的可用余额');
  365. }
  366. // 转账比例
  367. if ($this->type == self::BONUS_TO_BALANCE) {
  368. $isCanTransferProp = Cache::getSystemConfig()['isCanTransferProp']['VALUE'];
  369. if ($isCanTransferProp == 1) {
  370. $maxAmount = Tool::formatPrice($this->_fromUserInfo['TRANSFER_PROP'] * Balance::getAvailableBalance($this->_fromUserInfo['ID']) * 0.01);
  371. if ($this->amount > $maxAmount) {
  372. $this->addError($attribute, '转账金额超出转账比例限额');
  373. }
  374. }
  375. }
  376. //手续费
  377. if($this->_transferConfig['fee']!=0){
  378. $fee = Tool::formatPrice($this->amount * ($this->_transferConfig['fee']) * 0.01);
  379. if($this->_transferConfig['feeMin']!=0&&$fee<$this->_transferConfig['feeMin']){
  380. $fee = $this->_transferConfig['feeMin'];
  381. }
  382. if($this->_transferConfig['feeMax']!=0&&$fee>$this->_transferConfig['feeMax']){
  383. $fee = $this->_transferConfig['feeMax'];
  384. }
  385. $this->_fee = $fee;
  386. }
  387. }
  388. /**
  389. * 转账类型判断
  390. * @param $attribute
  391. */
  392. public function isType($attribute) {
  393. if (!in_array($this->type, self::allowTransferType)) {
  394. $this->addError($attribute, '不允许的转账类型');
  395. }
  396. //获取转账参数
  397. if(!$this->_transferConfig = Json::decode(Cache::getSystemConfig()['allowWallet']['VALUE'])[$this->type-1]){
  398. $this->addError($attribute, '错误的转账类型');
  399. }
  400. if(!$this->_transferConfig['isOpen']){
  401. $this->addError($attribute, '不可用的转账类型');
  402. }
  403. }
  404. /**
  405. * 校验支付密码
  406. * @param $attribute
  407. * @param $params
  408. */
  409. public function validatePassword($attribute, $params) {
  410. $uid = \Yii::$app->user->id;
  411. if(!$this->toUserName || !$this->toRealName || $this->amount == 0){
  412. $this->addError($attribute, '转账失败');
  413. }else if(!$this->_fromUserInfo){
  414. LoggerTool::info('transfer error, '.$uid.' '. $this->amount.' '. $this->toUserName);
  415. $this->addError($attribute, '转账时发生错误');
  416. }else if (!User::validatePayPassword($this->_fromUserInfo['ID'], $this->payPassword)) {
  417. $this->addError($attribute, '支付密码不正确');
  418. }
  419. }
  420. public function validateCode($attribute, $params) {
  421. $uid = \Yii::$app->user->id;
  422. $redisCode = \Yii::$app->redis->getset('transferCode_'.$uid,'');
  423. \Yii::$app->redis->del('transferCode_'.$uid);
  424. if ($this->transferCode!=$redisCode) {
  425. $this->addError($attribute, '转账校验失败'.$redisCode);
  426. }
  427. }
  428. /**
  429. * 生成随机数
  430. * @param $length
  431. * @param int $numeric
  432. * @return string
  433. */
  434. public function random($length, $numeric = 0) {
  435. $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
  436. $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
  437. $hash = '';
  438. $max = strlen($seed) - 1;
  439. for ($i = 0; $i < $length; $i++) {
  440. $hash .= $seed[mt_rand(0, $max)];
  441. }
  442. return $hash;
  443. }
  444. /**
  445. * 转账
  446. * @return Transfer|null
  447. * @throws \Exception
  448. */
  449. public function transfer() {
  450. if (!$this->validate()) {
  451. return null;
  452. }
  453. $fromData = Balance::getLogData($this->_fromUserInfo['ID']);
  454. $toData = Balance::getLogData($this->_toUserInfo['ID']);
  455. if ($this->_fromUserInfo['ID']==$this->_toUserInfo['ID'] && $this->_transferConfig['out']==$this->_transferConfig['in']){
  456. throw new \Exception('不能给同一账户转账');
  457. }
  458. $this->userOperateLogger->saveBeforeContent=array_merge($fromData,$toData);
  459. $db = \Yii::$app->db;
  460. $transaction = $db->beginTransaction();
  461. try {
  462. $amount = Tool::formatPrice($this->amount - $this->_fee);
  463. // 转账记录
  464. $period = Period::instance();
  465. $model = new Transfer();
  466. $model->ID = SnowFake::instance()->generateId();
  467. $model->TRANSFER_SN = Transfer::generateSN();
  468. $model->OUT_UID = $this->_fromUserInfo['ID'];
  469. $model->LAST_OUT_USER_NAME = $this->_fromUserInfo['USER_NAME'];
  470. $model->LAST_OUT_REAL_NAME = $this->_fromUserInfo['REAL_NAME'];
  471. $model->LAST_OUT_DEC_LV = $this->_fromUserInfo['DEC_LV'];
  472. $model->LAST_OUT_DEC_ROLE_ID = $this->_fromUserInfo['DEC_ROLE_ID'];
  473. $model->OUT_WALLET = $this->_transferConfig['out'];
  474. $model->LAST_OUT_SYSTEM_ID = $this->_fromUserInfo['SYSTEM_ID'] ? $this->_fromUserInfo['SYSTEM_ID'] : '';
  475. $model->IN_UID = $this->_toUserInfo['ID'];
  476. $model->LAST_IN_USER_NAME = $this->_toUserInfo['USER_NAME'];
  477. $model->LAST_IN_REAL_NAME = $this->_toUserInfo['REAL_NAME'];
  478. $model->LAST_IN_DEC_LV = $this->_toUserInfo['DEC_LV'];
  479. $model->IN_WALLET = $this->_transferConfig['in'];
  480. $model->LAST_IN_SYSTEM_ID = $this->_toUserInfo['SYSTEM_ID'] ? $this->_toUserInfo['SYSTEM_ID'] : '';
  481. $model->ORI_AMOUNT = $this->amount;
  482. $model->FEE = $this->_fee;
  483. $model->AMOUNT = $amount;
  484. $model->REMARK = $this->remark;
  485. $model->PERIOD_NUM = $period->getNowPeriodNum();
  486. $model->CALC_MONTH = $period->getNowYearMonth();
  487. $model->CREATED_AT = Date::nowTime();
  488. if (!$model->save()) {
  489. throw new Exception(Form::formatErrorsForApi($model->getErrors()));
  490. }
  491. if ($this->type == self::BONUS_TO_BALANCE) {
  492. // 会员金额减少
  493. 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]);
  494. 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]);
  495. } elseif($this->type == self::BONUS_TO_BONUS) {
  496. // 会员金额减少
  497. 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]);
  498. 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]);
  499. }else if ($this->type == self::BALANCE_TO_BALANCE) {
  500. // 会员金额减少
  501. 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]);
  502. 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]);
  503. } else if ($this->type == self::POINT_TO_BALANCE) {
  504. // 复消积分转余额
  505. // 减少复消积分
  506. Balance::changeUserBonus(
  507. $this->_fromUserInfo['ID'],
  508. 'reconsume_points',
  509. -abs($this->amount),
  510. [
  511. 'TRANSFER_SN' => $model->TRANSFER_SN,
  512. 'DEAL_TYPE_ID' => DealType::TRANSFER_OUT,
  513. 'REMARK' => 'To:' . $this->_toUserInfo['USER_NAME'] . ',' . $this->remark
  514. ]
  515. );
  516. // 增加余额
  517. Cash::changeUserCash(
  518. $this->_toUserInfo['ID'],
  519. 'CASH', abs($amount),
  520. [
  521. 'TRANSFER_SN' => $model->TRANSFER_SN,
  522. 'DEAL_TYPE_ID' => DealType::TRANSFER_IN,
  523. 'REMARK' => 'From:' . $this->_fromUserInfo['USER_NAME'] . ',' . $this->remark
  524. ]
  525. );
  526. } else {
  527. throw new \Exception('错误的交易类型');
  528. }
  529. $transaction->commit();
  530. } catch (Exception $e) {
  531. $transaction->rollBack();
  532. $this->addError('edit', $e->getMessage());
  533. return null;
  534. }
  535. $fromData = Balance::getLogData($this->_fromUserInfo['ID']);
  536. $toData = Balance::getLogData($this->_toUserInfo['ID']);
  537. $this->userOperateLogger->saveAfterContent=array_merge($fromData,$toData);
  538. unset($fromData,$toData);
  539. $this->userOperateLogger->clean()->save([
  540. 'optType' => '会员转账',
  541. 'userId' => \Yii::$app->user->id,
  542. 'userName' => Info::getUserNameByUserId(\Yii::$app->user->id),
  543. 'remark' => $this->remark,
  544. ]);
  545. return $model;
  546. }
  547. }