| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- <?php
- namespace addons\Happiness\common\logic\pv;
- use addons\Happiness\common\enums\HappinessEnum;
- use addons\Happiness\common\enums\HappinessPvEnum;
- use addons\Happiness\common\models\HappinessPvWallet;
- use addons\Happiness\common\models\HappinessPvWalletLog;
- use common\enums\RabbitMqEnum;
- use common\enums\RedisKeyEnum;
- use common\enums\StatusEnum;
- use common\helpers\LockHelper;
- use common\helpers\TaskHelper;
- use common\models\common\CapitalLog;
- use common\traits\ErrorTrait;
- use Exception;
- use Yii;
- /**
- * Class WalletLogic
- * 新积分处理类
- */
- class WalletLogic
- {
- use ErrorTrait;
- /**
- * 获取资金类型
- * @return array
- */
- public static function getWalletType()
- {
- return [
- 'score_value',
- 'total_score_value',
- 'freeze_score_value',
- 'active_score_value'
- ];
- }
- public static function handle($data, $task_id = 0)
- {
- $user_id = $data['user_id'];
- $wallet_type = $data['wallet_type'];
- $mall_id = $data['mall_id'];
- $capital_types = self::getWalletType();
- if (!in_array($wallet_type, $capital_types)) {
- self::$static_error = '操作类型有误';
- Yii::error(__CLASS__ . ' handle error :' . self::$static_error);
- return false;
- }
- if(bccomp($data['change_num'],0,10) == 0){
- self::$static_error = '操作金额为0';
- Yii::error(__CLASS__ . ' handle error :' . self::$static_error);
- return false;
- }
- //lock
- $lock_key = RedisKeyEnum::suffix(HappinessPvEnum::HAPPINESS_PV_USER_WALLET, $user_id);
- $identification = uniqid();
- if (LockHelper::lock($lock_key, $identification, 100, 100)) {
- $t = \Yii::$app->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;
- }
- }
- }
|