| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- <?php
- namespace addons\Happiness\common\logic\voucher;
- use addons\Happiness\common\enums\HappinessEnum;
- use addons\Happiness\common\enums\HappinessVoucherEnum;
- use addons\Happiness\common\models\HappinessVoucherWallet;
- use addons\Happiness\common\models\HappinessVoucherLog;
- 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
- * 权重值处理类
- * @Author: zfh
- * @DateTime: 2024/05/06 20:39
- * @Copyright: copyright (c) 2023 广东七件事集团
- */
- class WalletLogic
- {
- use ErrorTrait;
- /**
- * 获取资金类型
- * @return array
- */
- public static function getWalletType()
- {
- return [
- 'balance'
- ];
- }
- public static function handle($data, $task_id = 0)
- {
- if (!empty($data['message_id'])) {
- $task_id = $data['message_id'];
- unset($data['message_id']);
- }
- $store_id = $data['store_id'];
- $wallet_type = $data['wallet_type'];
- $mall_id = $data['mall_id'];
- $level=$data['level'];
- $unfreeze = $data['unfreeze'] ?? false; //是否操作解冻资金
- $freeze_log_id = $data['freeze_log_id'] ?? 0; //操作解冻资金的记录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;
- }
- if ($unfreeze){
- if($freeze_log_id <= 0){
- self::$static_error = '解冻资金记录ID不存在';
- Yii::error(__CLASS__ . ' handle error :' . self::$static_error);
- return false;
- }
- $unfreeze_log = HappinessVoucherWallet::findOne(['id' => $freeze_log_id,'store_id' => $store_id,'status' =>
- CapitalLog::STATUS_WAIT_SEND]);
- if(!$unfreeze_log){
- self::$static_error = '解冻资金记录不存在';
- Yii::error(__CLASS__ . ' handle error :' . self::$static_error);
- return false;
- }
- }
- //lock
- $lock_key = RedisKeyEnum::suffix(HappinessVoucherEnum::LOCK_HAPPINESS_USER_WALLET, $store_id);
- $identification = uniqid();
- if (1==1) {
- $t = \Yii::$app->db->beginTransaction();
- try {
- $edit_field = $wallet_type;
- //修改用户钱包表
- $user_wallet_model = HappinessVoucherWallet::findOne(['mall_id' => $mall_id, 'store_id' => $store_id, 'status' =>
- StatusEnum::ENABLED,'level'=>$level]);
- if (empty($user_wallet_model)) {
- $user_wallet_model = HappinessVoucherWallet::setData([
- 'store_id' => $store_id,
- 'mall_id' => $mall_id,
- 'level'=>$level,
- 'balance'=>0,
- 'freeze_balance'=>0,
- 'status' => StatusEnum::ENABLED
- ]);
- if($user_wallet_model===false)
- {
- throw new Exception(HappinessVoucherWallet::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());
- //操作解冻:添加余额,修改记录状态
- if ($unfreeze){
- //查询记录
- $log_res = HappinessVoucherLog::updateAll(['status' => CapitalLog::STATUS_SEND,'after_num' => $after_num],['id' =>
- $freeze_log_id]);
- if (!$log_res) throw new Exception(HappinessVoucherLog::getStaticError());
- $log_res_id = $freeze_log_id;
- }else{
- $setData = [
- 'mall_id' => $mall_id,
- 'store_id' => $store_id,
- 'level'=>$level,
- 'change_type' => $data['change_num'] > 0 ? CapitalLog::CHANGE_TYPE_ADD : CapitalLog::CHANGE_TYPE_SUB,
- 'change_num' => abs($data['change_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'] ?? HappinessVoucherEnum::ADDONS_NAME,
- 'status' => 1,
- 'order_no' => $data['order_no'] ?? ''
- ];
- $log_res = HappinessVoucherLog::setData($setData);
- if (!$log_res) throw new Exception(HappinessVoucherLog::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 = HappinessVoucherEnum::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 = HappinessVoucherEnum::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;
- }
- /**
- * 处理 未处理记录
- * @return void
- * @throws
- */
- public static function unfrozen($frozen_log)
- {
- if($frozen_log['status'] != CapitalLog::STATUS_WAIT_SEND) return ;
- $res = self::handleInQueue($frozen_log);
- if($res){
- HappinessVoucherLog::updateAll(['status' => CapitalLog::STATUS_SEND],['id' => $frozen_log['id']]);
- }
- return true;
- }
- /**
- * 删除未处理记录
- * @param $frozen_log
- * @return void
- */
- public static function delfrozen($frozen_log)
- {
- if($frozen_log['status'] != CapitalLog::STATUS_WAIT_SEND) return ;
- HappinessVoucherLog::updateAll(['status' => CapitalLog::STATUS_FAIL],['id' => $frozen_log['id']]);
- return true;
- }
- }
|