db->beginTransaction(); try { $edit_field = $wallet_type; //修改用户钱包表 $user_wallet_model = HappinessPvWallet::findOne(['mall_id' => $mall_id, 'user_id' => $user_id]); if (empty($user_wallet_model)) { $user_wallet_model = HappinessPvWallet::setData([ 'user_id' => $user_id, 'mall_id' => $mall_id, 'score_value' => 0, 'freeze_score_value' => 0, 'active_score_value' => 0, 'status' => StatusEnum::ENABLED, 'total_score_value' => 0, ]); if($user_wallet_model===false) throw new Exception(HappinessPvWallet::getStaticError()); } $current_num = $user_wallet_model->$edit_field; $after_num = bcadd($current_num, $data['change_num'], 10); if (bccomp($after_num, 0, 10) < 0) { throw new Exception('用户新积分余额不足'); } $user_wallet_model->$edit_field = $after_num; if (!$user_wallet_model->save()) throw new Exception($user_wallet_model->getErrorMessage()); //操作解冻:添加余额,修改记录状态 $setData = [ 'mall_id' => $mall_id, 'user_id' => $user_id, 'change_type' => $data['change_num'] > 0 ? CapitalLog::CHANGE_TYPE_ADD : CapitalLog::CHANGE_TYPE_SUB, 'change_num' => abs($data['change_num']), 'before_num' => $current_num, 'after_num' => $after_num, 'desc' => $data['desc'] ?? '', 'source_table' => $data['source_table'] ?? '', 'source_table_id' => $data['source_table_id'] ?? 0, 'from_type' => $data['from_type'] ?? '', 'wallet_type' => $data['wallet_type'], 'addon_name' => $data['addon_name'] ?? HappinessEnum::ADDONS_NAME, 'status' => 1, 'order_no' => $data['order_no'] ?? '' ]; $log_res = HappinessPvWalletLog::setData($setData); if (!$log_res) throw new Exception(HappinessPvWalletLog::getStaticError()); $log_res_id = $log_res->id; $t->commit(); //unlock LockHelper::uLock($lock_key, $identification); $task_id && self::setHandleResult($task_id, $log_res_id); return true; } catch (Exception $e) { Yii::error(__CLASS__ . ' handle exception : ' . $e->getMessage() . ',task_id:' . $task_id.',data:'.json_encode($data)); $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 = HappinessPvEnum::USER_WALLET_RESULT_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 = HappinessPvEnum::USER_WALLET_RESULT_KEY_PREFIX . $task_id; $redis = \Yii::$app->redis; return $redis->executeCommand('SET', [$result_key, $result, 'EX', 86400]); } /** * 异步队列操作用户钱包 * @param array $data * @param bool $wait_result 是否阻塞,等待结果 * @throws * @return bool */ public static function handleInQueue($data, $wait_result = true) { if (!in_array($data['wallet_type'], self::getWalletType())) { throw new Exception('操作类型不合法'); } $task_id = TaskHelper::pushTaskQueue( RabbitMqEnum::EXCHANGE_TASK_USER_WALLET, RabbitMqEnum::USER_WALLET_QUEUE, $data, __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; } public static function batchHandle($data) { //外部加个事务 try { unset($data['message_id']); foreach ($data as $log) { if(!isset($log['message_id'])) $log['message_id'] = ''; $log['message_id'] = 0; $res=self::handle($log); if($res===false) { throw new Exception(self::getStaticError()); } } return true; }catch (Exception $e) { Yii::error(__CLASS__ . ' batchHandle exception : ' . $e->getMessage() . ',data:'.json_encode($data)); self::$static_error = $e->getMessage(); return false; } } }