'积分', self::WALLET_TYPE_FROZEN_SCORE => '冻结积分', self::WALLET_TYPE_BALANCE => '余额', self::WALLET_TYPE_FROZEN_BALANCE => '冻结余额', self::WALLET_TYPE_COMMISSION => '佣金', self::WALLET_TYPE_FROZEN_COMMISSION => '冻结佣金', ]; return $arr[$type] ?? ''; } /** * 异步队列操作用户钱包 * @param int $mall_id * @param int $user_id * @param string $wallet_type 操作类型:score,balance,commission * @param float $money 操作金额,负数:减少/正数:增加 * @param bool $is_frozen 是否操作冻结资金 * @param string $desc 操作描述 * @param string $source 来源 * @param int $source_id 来源业务ID * @param bool $wait_result 是否阻塞,等待结果 * @throws * @return bool */ public static function handleByQueue($mall_id, $user_id, $wallet_type, $money, $is_frozen = false, $desc = '', $source = '', $source_id = 0, $wait_result = true) { if (!in_array($wallet_type, [self::WALLET_TYPE_SCORE, self::WALLET_TYPE_BALANCE, self::WALLET_TYPE_COMMISSION])) { throw new Exception('操作类型不合法'); } $task_id = TaskHelper::pushTaskQueue( RabbitMqEnum::EXCHANGE_TASK_USER_WALLET, RabbitMqEnum::USER_WALLET_QUEUE, ['mall_id' => $mall_id, 'user_id' => $user_id, 'wallet_type' => $wallet_type, 'money' => $money, 'is_frozen' => $is_frozen, 'desc' => $desc, 'source' => $source, 'source_id' => $source_id], __CLASS__, 'handle' ); if (!$task_id) { throw new Exception('操作失败'); } $result = true; //block for result if ($wait_result) { $hasWait = 0; //已经等待的时间:毫秒 $max_wait_time = 3 * 1000; //最长等待 3s while (true) { $result = self::getHandleResult($task_id); if ($result) { break; } usleep(30 * 1000);//等待30ms $hasWait += 30; if ($hasWait > $max_wait_time) { //等待超时 $result = false; break; } } } //注意:返回false 表示正在等待处理 return $result; } /** * 异步队列-批量操作用户钱包 * @param $data * [ * ['mall_id' => $mall_id,'user_id'=>1,'is_frozen'=>true,'not_add_total'=>true,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type'], * ['mall_id' => $mall_id,'user_id'=>2,'is_frozen'=>false,'not_add_total'=>false,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type'], * ] * @return bool * @throws Exception */ public static function batchHandleByQueue($data) { $capital_types = self::getWalletType(); $function = 'batchHandle'; //判断data 数据格式 foreach ($data as $val) { if (empty($val['user_id'])) { throw new Exception('参数不合法 ,user_id 不能为空'); } if (empty($val['mall_id'])) { throw new Exception('参数不合法 ,mall_id 不能为空'); } if (!in_array($val['wallet_type'], $capital_types)) { throw new Exception('操作类型不合法'); } $change_type[] = $val['money'] > 0 ? 'add' : 'sub'; } //操作类型不一致 $change_type = array_unique($change_type); if(count($change_type) > 1) $function = 'batchHandleByTransaction'; $task_id = TaskHelper::pushTaskQueue( RabbitMqEnum::EXCHANGE_TASK_USER_WALLET, RabbitMqEnum::USER_WALLET_QUEUE, $data, __CLASS__, $function ); if (!$task_id) { throw new Exception('操作失败'); } return true; } /** * 批量操作用户钱包 * @param int $task_id mq消费message_id * @param array $data * [ * ['mall_id' => $mall_id,'user_id'=>1,'is_frozen'=>true,'not_add_total'=>true,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type','order_no'=>$order_no,'contributor_name'=>$contributor_name,'contributor_id'=>$contributor_id,'contributor_money'=>$contributor_money], * ['mall_id' => $mall_id,'user_id'=>2,'is_frozen'=>false,'not_add_total'=>false,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type','order_no'=>$order_no,'contributor_name'=>$contributor_name,'contributor_id'=>$contributor_id,'contributor_money'=>$contributor_money], * * ] * @throws * @return bool * */ public static function batchHandle($data) { $task_id = 0; if(!empty($data['message_id'])){ $task_id = $data['message_id']; unset($data['message_id']); } $user_handles = []; $capital_log_list = [];// 提交数据记录类型 foreach ($data as $val) { $wallet_type = empty($val['is_frozen']) ? $val['wallet_type'] : 'frozen_'.$val['wallet_type']; $capital_log_type = empty($val['is_frozen']) ? $val['wallet_type'] : $val['wallet_type'] . '_frozen'; if (!in_array($capital_log_type, $capital_log_list)) { $capital_log_list[] = $capital_log_type; } $user_handles[$val['user_id']][$wallet_type][] = $val; } $error = []; $time = time(); $user_wallet_list = []; $mall_id = $data[0]['mall_id']; foreach ($user_handles as $user_id => $handle) { $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_USER_WALLET , $user_id); $identification = uniqid(); if (!LockHelper::lock($lock_key, $identification, 100, 100)) { Yii::error(__CLASS__ . ' batchHandle error : 抢不到锁,task_id:' . $task_id); continue; } $user_wallet_model = UserWallet::findOne(['user_id' => $user_id, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($user_wallet_model)) { $error[] = ['user_id' => $user_id, 'type' => '', 'params' => json_encode($handle), 'error_msg' => '用户钱包不存在']; continue; } foreach ($handle as $wallet_type => $logs) { $is_frozen = false; if (strpos($wallet_type, 'frozen') !== false) { $is_frozen = true; } //求和 $money = array_sum(array_column($logs, 'money')); if (!is_numeric($money) || empty($money)) { continue; } $current_num = $user_wallet_model->$wallet_type; /*if ($current_num + $money < 0) { $error[] = ['user_id' => $user_id, 'type' => $wallet_type, 'params' => json_encode($logs), 'error_msg' => '用户' . self::getWalletTypeMsg($wallet_type) . '不足']; continue; }*/ foreach ($logs as $key => $log) { //操作非冻结资金 $wallet_type = $log['wallet_type']; $frozen_field = 'frozen_'.$wallet_type; $total_field = 'total_' . $wallet_type; $total_use_field = 'total_use_' . $wallet_type; if ($log['is_frozen']) { $user_wallet_model->$frozen_field += $log['money'];//冻结 }else{ $user_wallet_model->$wallet_type += $log['money'];//非冻结 } if ($log['is_frozen']==false&&empty($log['not_add_total'])) { $log['money'] > 0 && $user_wallet_model->$total_field += $log['money'];//总数 } if ($log['capital_type'] != UserWalletEnum::WITHDRAWAL_DECR) { $log['is_frozen'] == false && $log['money'] < 0 && $user_wallet_model->$total_use_field += abs($log['money']);//已使用 } } $trans = Yii::$app->db->beginTransaction(); if (!$user_wallet_model->save()) { $error[] = ['user_id' => $user_id, 'wallet_type' => $wallet_type, 'logs' => $logs, 'error_msg' => $user_wallet_model->getErrorMessage()]; $trans->rollBack(); continue; } $values_arr = []; foreach ($logs as $key => $log) { if($log['is_frozen']) $is_frozen = true; $info = [ $log['mall_id'], $log['user_id'], $log['money'] >= 0 ? CapitalLog::CHANGE_TYPE_ADD : CapitalLog::CHANGE_TYPE_SUB, abs($log['money']), $current_num, $log['desc'], $log['source_table'], $log['source_table_id'], $log['from_type'], $log['capital_type'], $time, $time, $log['order_no']??'', $log['contributor_name']??'', $log['contributor_money']??0, $log['contributor_id']??0, ]; $is_frozen && $info[] = CapitalLog::STATUS_WAIT_SEND; if(isset($log['service_charge'])){ $info[] = $log['service_charge']; } $values_arr[] = $info; $current_num = $current_num + $log['money']; } $fields = ['mall_id', 'user_id', 'change_type', 'change_num', 'current_num', 'desc', 'source_table', 'source_table_id','from_type', 'capital_type','created_at', 'updated_at','order_no','contributor_name','contributor_money','contributor_id']; if ($is_frozen) { //操作冻结资金 CapitalLog::$capitalType = str_replace('frozen_', '', $wallet_type) . '_frozen'; $fields[] = 'status'; } else { CapitalLog::$capitalType = $wallet_type; } if(isset($log['service_charge'])){ $fields[] = 'service_charge'; } Yii::$app->db->createCommand()->batchInsert( CapitalLog::tableName(), $fields, $values_arr )->execute(); if(UserFreezeCommission::setLogData($user_id, $logs) === false) { $error[] = ['user_id' => $user_id, 'wallet_type' => $wallet_type, 'logs' => $logs, 'error_msg' => 'from qimall_user_freeze_commission err: '.UserFreezeCommission::getStaticError()]; } // 重新编写用户金额管理 $user_wallet_list[] = ['user_id' => $user_id, 'wallet_type' => $wallet_type, 'logs' => $logs]; $trans->commit(); } LockHelper::uLock($lock_key, $identification); } // 操作积分-余额-佣金 日志 foreach ($capital_log_list as $item){ $log_value = ['time' => $time, 'capitalType' => $item]; \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, $log_value, CapitalLogRelation::class, 'addLog'); } $event = new UserWalletEvent($mall_id); \Yii::$app->services->events->dispatch($event, ['mall_id' => $mall_id, 'user_wallet_list' => $user_wallet_list], $event->listeners); if ($error) { //记录错误信息 foreach ($error as $err) { $log = new CapitalErrorLog(); $log->attributes = $err; $log->save(); } } return true; } /** * 批量操作用户钱包 强一致性【在一个事务内完成 所有操作】 * @param int $task_id mq消费message_id * @param array $data * [ * ['mall_id' => $mall_id,'user_id'=>1,'is_frozen'=>true,'not_add_total'=>true,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type','order_no'=>$order_no,'contributor_name'=>$contributor_name,'contributor_id'=>$contributor_id,'contributor_money'=>$contributor_money], * ['mall_id' => $mall_id,'user_id'=>2,'is_frozen'=>false,'not_add_total'=>false,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type','order_no'=>$order_no,'contributor_name'=>$contributor_name,'contributor_id'=>$contributor_id,'contributor_money'=>$contributor_money], * * ] * @throws * @return bool * */ public static function batchHandleByTransaction($data) { $trans = Yii::$app->db->beginTransaction(); try{ $task_id = 0; if(!empty($data['message_id'])){ $task_id = $data['message_id']; unset($data['message_id']); } Yii::error(__CLASS__ . ' batchHandleByTransaction task_id : ,task_id:' . $task_id); $user_handles = []; $capital_log_list = [];// 提交数据记录类型 foreach ($data as $val) { $wallet_type = empty($val['is_frozen']) ? $val['wallet_type'] : 'frozen_'.$val['wallet_type']; $capital_log_type = empty($val['is_frozen']) ? $val['wallet_type'] : $val['wallet_type'] . '_frozen'; if (!in_array($capital_log_type, $capital_log_list)) { $capital_log_list[] = $capital_log_type; } $user_handles[$val['user_id']][$wallet_type][] = $val; } // 因为所有传来列表mall_id相同 所以拿取第一个数组的mall_id赋值 $mall_id = $data[0]['mall_id']; $user_wallet_list = []; $time = time(); foreach ($user_handles as $user_id => $handle) { $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_USER_WALLET , $user_id); $identification = uniqid(); if (!LockHelper::lock($lock_key, $identification, 100, 100)) { throw new Exception(__CLASS__ . ' batchHandle error : 抢不到锁,task_id:' . $task_id); } $user_wallet_model = UserWallet::findOne(['user_id' => $user_id, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($user_wallet_model)) { LockHelper::uLock($lock_key, $identification); throw new Exception("{$user_id}用户钱包不存在"); } foreach ($handle as $wallet_type => $logs) { $is_frozen = false; if (strpos($wallet_type, 'frozen') !== false) { $is_frozen = true; } //求和 $money = array_sum(array_column($logs, 'money')); if (!is_numeric($money) || empty($money)) { continue; } $current_num = $user_wallet_model->$wallet_type; /*因为新需求可以导入负数所以注释此段代码 if ($current_num + $money < 0) { LockHelper::uLock($lock_key, $identification); throw new Exception("{$user_id}用户".self::getWalletTypeMsg($wallet_type)."不足"); //$error[] = ['user_id' => $user_id, 'type' => $wallet_type, 'params' => json_encode($logs), 'error_msg' => '用户' . self::getWalletTypeMsg($wallet_type) . '不足']; }*/ foreach ($logs as $key => $log) { //操作非冻结资金 $wallet_type = $log['wallet_type']; $frozen_field = 'frozen_'.$wallet_type; $total_field = 'total_' . $wallet_type; $total_use_field = 'total_use_' . $wallet_type; if ($log['is_frozen']) { $user_wallet_model->$frozen_field += $log['money'];//冻结 }else{ $user_wallet_model->$wallet_type += $log['money'];//非冻结 } if ($log['is_frozen']==false&&empty($log['not_add_total'])) { $log['money'] > 0 && $user_wallet_model->$total_field += $log['money'];//总数 } if ($log['capital_type'] != UserWalletEnum::WITHDRAWAL_DECR) { $log['is_frozen'] == false && $log['money'] < 0 && $user_wallet_model->$total_use_field += abs($log['money']);//已使用 } } if (!$user_wallet_model->save()) { LockHelper::uLock($lock_key, $identification); throw new Exception("{$user_id}用户".self::getWalletTypeMsg($wallet_type)." error".$user_wallet_model->getErrorMessage()); } $values_arr = []; foreach ($logs as $key => $log) { if($log['is_frozen']) $is_frozen = true; $info = [ $log['mall_id'], $log['user_id'], $log['money'] >= 0 ? CapitalLog::CHANGE_TYPE_ADD : CapitalLog::CHANGE_TYPE_SUB, abs($log['money']), $current_num, $log['desc'], $log['source_table'], $log['source_table_id'], $log['from_type'], $log['capital_type'], $time, $time, $log['order_no']??'', $log['contributor_name']??'', $log['contributor_money']??0, $log['contributor_id']??0, ]; $is_frozen && $info[] = CapitalLog::STATUS_WAIT_SEND; if(isset($log['service_charge'])){ $info[] = $log['service_charge']; } $values_arr[] = $info; $current_num = $current_num + $log['money']; } $fields = ['mall_id', 'user_id', 'change_type', 'change_num', 'current_num', 'desc', 'source_table', 'source_table_id','from_type', 'capital_type','created_at', 'updated_at','order_no','contributor_name','contributor_money','contributor_id']; if ($is_frozen) { //操作冻结资金 CapitalLog::$capitalType = str_replace('frozen_', '', $wallet_type) . '_frozen'; $fields[] = 'status'; } else { CapitalLog::$capitalType = $wallet_type; } if(isset($log['service_charge'])){ $fields[] = 'service_charge'; } Yii::$app->db->createCommand()->batchInsert( CapitalLog::tableName(), $fields, $values_arr )->execute(); if(UserFreezeCommission::setLogData($user_id, $logs) === false) { \Yii::error(__METHOD__.' from qimall_user_freeze_commission err: '.UserFreezeCommission::getStaticError()); } $user_wallet_list[] = ['user_id' => $user_id, 'wallet_type' => $wallet_type, 'logs' => $logs]; } LockHelper::uLock($lock_key, $identification); } $trans->commit(); // 操作积分-余额-佣金 日志 foreach ($capital_log_list as $item){ $log_value = ['time' => $time, 'capitalType' => $item]; \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, $log_value, CapitalLogRelation::class, 'addLog'); } // 修改事务请求 $event = new UserWalletEvent($mall_id); \Yii::$app->services->events->dispatch($event, ['mall_id'=>$mall_id, 'user_wallet_list' => $user_wallet_list], $event->listeners); }catch(Exception $e){ $trans->rollBack(); Yii::error(__CLASS__ . ' batchHandleByTransaction exception : ' . $e->getMessage() . ',task_id:' . $task_id); self::$static_error = $e->getMessage(); return ; } return true; } /** * 直接操作用户钱包 * * @param int $task_id * @param array $data * ['mall_id' => $mall_id,'user_id'=>1,'is_frozen'=>true,'not_add_total'=>true,'wallet_type'=>'balance','money'=>1,'desc'=> '操作描述','source_table' => $source,'source_table_id' => $source_id,'from_type'=>$from_type','capital_type'=>$capital_type','order_no'=>$order_no,'contributor_name'=>$contributor_name,'contributor_id'=>$contributor_id,'contributor_money'=>$contributor_money], * @param boolean $is_trans 是否启用事务 * @return bool */ public static function handle($task_id, $data, bool $is_trans = true) { $task_id = 0; if(!empty($data['message_id'])){ $task_id = $data['message_id']; unset($data['message_id']); } $user_id = $data['user_id']; $wallet_type = $data['wallet_type']; $is_frozen = $data['is_frozen'] ?? false; //是否操作冻结资金 $unfrozen = $data['unfrozen'] ?? false; //是否操作解冻资金 $capital_types = self::getWalletType(); if (!in_array($wallet_type, $capital_types)) { self::$static_error = '操作类型有误'; return false; } //lock $lock_key = RedisKeyEnum::suffix(RedisKeyEnum::LOCK_USER_WALLET , $user_id); $identification = uniqid(); if (LockHelper::lock($lock_key, $identification, 100, 100)) { $is_trans && $t = \Yii::$app->db->beginTransaction(); try { $edit_field = empty($is_frozen) ? $wallet_type : 'frozen_' . $wallet_type; $edit_use_field = 'total_use_' . $wallet_type; //修改用户钱包表 $user_wallet_model = UserWallet::findOne(['user_id' => $user_id, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]); if (empty($user_wallet_model)) throw new Exception('服务不存在或已删除'); $current_num = $user_wallet_model->$edit_field; if ($data['money'] < 0 && bcadd($current_num, $data['money'],2) < 0) { throw new Exception('用户' . self::getWalletTypeMsg($edit_field) . '不足'); } $frozen_field = 'frozen_' . $edit_field; if($unfrozen && abs($user_wallet_model->$frozen_field) < $data['money']){ throw new Exception('用户' . self::getWalletTypeMsg($frozen_field) . '不足'); } $user_wallet_model->$edit_field += $data['money']; if ($data['capital_type'] != UserWalletEnum::WITHDRAWAL_DECR) { empty($is_frozen) && $data['money'] < 0 && $user_wallet_model->$edit_use_field += abs($data['money']); } if (strpos($edit_field, 'frozen') === false && $data['money'] > 0) { $total_field = 'total_' . $edit_field; if (empty($data['no_change_field']) || !in_array($total_field, $data['no_change_field'])){ $user_wallet_model->$total_field += $data['money']; } if($unfrozen){ $frozen_field = 'frozen_' . $edit_field; $user_wallet_model->$frozen_field -= $data['money']; } } if (!$user_wallet_model->save()) throw new Exception($user_wallet_model->getErrorMessage()); $setData = [ 'mall_id' => $data['mall_id'], 'user_id' => $data['user_id'], 'change_type' => $data['money'] >= 0 ? CapitalLog::CHANGE_TYPE_ADD : CapitalLog::CHANGE_TYPE_SUB, 'change_num' => abs($data['money']), 'current_num' => $current_num, 'desc' => $data['desc'] ?? '', 'source_table' => $data['source_table'] ?? '', 'source_table_id' => $data['source_table_id'] ?? 0, 'from_type' => $data['from_type'] ?? '', 'capital_type' => $data['capital_type'] ?? '', 'order_no' => $data['order_no'] ?? '', 'contributor_name' => $data['contributor_name'] ?? '', 'contributor_id' => $data['contributor_id'] ?? 0, 'contributor_money' => $data['contributor_money'] ?? 0, ]; if(isset($data['change_type'])) { $setData['change_type'] = $data['change_type']; } if ($is_frozen) { //操作冻结资金 CapitalLog::$capitalType = $wallet_type . '_frozen'; $setData['status'] = CapitalLog::STATUS_WAIT_SEND; } else { CapitalLog::$capitalType = $wallet_type; } $is_send_message = false; if ($is_frozen && $data['money'] < 0 && !$unfrozen) { //取消冻结资金 不添加记录 add by zmz }else{ $is_send_message = true; $log_res = CapitalLog::setData($setData); if (!$log_res) { throw new Exception(CapitalLog::getStaticError()); } if(isset($data['service_charge'])){ $log_res->service_charge = $data['service_charge']; $log_res->save(); } } if(UserFreezeCommission::setLogData($user_id, [$data]) === false) { \Yii::error(__METHOD__.' from qimall_user_freeze_commission err: '.UserFreezeCommission::getStaticError()); } $is_trans && $t->commit(); //佣金到账微信公众号消息通知 if (CapitalLog::$capitalType == 'commission' && $data['money'] >= 0) { $obj = new WechatMessageLogic(); $obj->OrderCommissionSettle(['mall_id' => $data['mall_id'], 'user_id' => $data['user_id'], 'money' => abs($data['money'])]); } //unlock LockHelper::uLock($lock_key, $identification); $task_id && self::setHandleResult($task_id, true); if($is_send_message||!$is_frozen){ $send_message_data = [ 'user_id'=>$user_id, 'money'=>$data['money'], 'wallet_type'=>$wallet_type, 'mall_id' => $data['mall_id'], 'change_type'=>$setData['change_type'], ]; \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE, $send_message_data, WechatMessageLogic::class, 'receiptSendMessage'); } return true; } catch (Exception $e) { Yii::error(__CLASS__ . ' handle exception : ' . $e->getMessage() . ',task_id:' . $task_id); $is_trans && $t->rollBack(); LockHelper::uLock($lock_key, $identification); self::$static_error = $e->getMessage(); return false; } } else { //抢不到锁 Yii::error(__CLASS__ . ' handle error : 抢不到锁,task_id:' . $task_id); self::$static_error = '操作太频繁'; return false; } } /** * 获取处理结果 * @param $task_id * @return array|bool|null|string * @throws \yii\db\Exception */ public static function getHandleResult($task_id) { $result_key = RabbitMqEnum::USER_WALLET_RESUALT_KEY_PREFIX . $task_id; $redis = \Yii::$app->redis; return $redis->executeCommand('GET', [$result_key]); } /** * 获取处理结果 * @param $task_id * @param $result * @return array|bool|null|string * @throws \yii\db\Exception */ public static function setHandleResult($task_id, $result) { $result_key = RabbitMqEnum::USER_WALLET_RESUALT_KEY_PREFIX . $task_id; $redis = \Yii::$app->redis; return $redis->executeCommand('SET', [$result_key, $result, 'EX', 86400]); } /** * 解冻资金:将冻结金额 转换成 正常金额 * @param $log_id * @param $wallet_type * @param bool $is_send 是否发放 * @return bool */ public static function unfrozen($log_id, $wallet_type, $is_send = true) { try { $capital_types = self::getWalletType(); if (!in_array($wallet_type, $capital_types)) { throw new Exception('操作类型有误'); } CapitalLog::$capitalType = $wallet_type . '_frozen'; $log = CapitalLog::findOne(['id' => $log_id, 'status' => CapitalLog::STATUS_WAIT_SEND]); if (empty($log)) { throw new Exception('操作记录不存在'); } if ($is_send) { $log_arr = $log->toArray(); $log_arr['wallet_type'] = $wallet_type; $log_arr['is_frozen'] = false; if ($log['change_type'] == 'sub') { $log_arr['money'] = bcmul($log_arr['change_num'], -1, 2); } else { $log_arr['money'] = $log_arr['change_num']; } $log_arr['unfrozen'] = true; $res = self::handle(0, $log_arr); if (!$res) { throw new Exception(self::$static_error); } $status = CapitalLog::STATUS_SEND; } else { $log_arr = $log->toArray(); $log_arr['wallet_type'] = $wallet_type; $log_arr['is_frozen'] = true; //操作冻结 $log_arr['money'] = $log_arr['change_num'] * -1; $log_arr['unfrozen'] = false; //非解冻 $res = self::handle(0, $log_arr); $status = CapitalLog::STATUS_FAIL; } //修改记录状态 CapitalLog::$capitalType = $wallet_type . '_frozen'; if(!CapitalLog::updateAll(['status' =>$status ],['id' => $log_id])){ throw new Exception($log->getErrorMessage()); } return true; } catch (Exception $e) { Yii::error(__CLASS__ . ' unfrozen exception : ' . $e->getMessage()); self::$static_error = $e->getMessage(); return false; } } //获取用户上一次填写的提现信息 public function getPrevInfo($mall_id, $user_id, $params) { try { $where = [ ['mall_id' => $mall_id], ['user_id' => $user_id], ['from' => $params['from']], ['type' => $params['type']], ]; if (!empty($params['source'])) $where[] = ['source' => $params['source']]; // print_r($where);exit; $info = UserWithdrawLog::getOne($where, true, [], 'id desc'); if (empty($info)) return []; $info['extra'] = json_decode($info['extra'], true); if (empty($info['extra']['bank_account_type'])) $info['extra']['bank_account_type'] = 1; return $info['extra']; } catch (\Exception $e) { throw new Exception($e->getMessage()); } } }