算力扣费及列表接口

This commit is contained in:
wong
2025-09-19 16:51:03 +08:00
parent 9c1cfda40b
commit ce6e752905
2 changed files with 195 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
<?php
namespace app\chukebao\controller;
use app\chukebao\model\TokensRecord;
use library\ResponseHelper;
use think\Db;
class TokensRecordController extends BaseController
{
public function getList(){
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$type = $this->request->param('type', '');
$form = $this->request->param('form', '');
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
$where = [
['companyId','=',$companyId],
['userId' ,'=', $userId]
];
if ($type != '') {
$where[] = ['type','=',$type];
}
if ($form != '') {
$where[] = ['form','=',$form];
}
$query = TokensRecord::where($where);
$list = $query->where($where)->page($page,$limit)->order('id desc')->select();
$total = $query->count();
foreach ($list as &$item) {
if (in_array($item['type'],[1])){
$nickname = Db::table('s2_wechat_friend')->where(['id' => $item['friendIdOrGroupId']])->value('nickname');
$item['nickname'] = !empty($nickname) ? $nickname : '-';
}
if (in_array($item['type'],[2,3])){
$nickname = Db::table('s2_wechat_chatroom')->where(['id' => $item['friendIdOrGroupId']])->value('nickname');
$item['nickname'] = !empty($nickname) ? $nickname : '-';
}
}
unset($item);
return ResponseHelper::success(['list'=>$list,'total'=>$total]);
}
public function consumeTokens($data = [])
{
if (empty($data)){
return ResponseHelper::error('数据缺失');
}
$tokens = isset($data['tokens']) ? intval($data['tokens']) : 0;
$type = isset($data['type']) ? intval($data['type']) : 0;
$form = isset($data['form']) ? intval($data['form']) : 0;
$wechatAccountId = isset($data['wechatAccountId']) ? intval($data['wechatAccountId']) : 0;
$friendIdOrGroupId = isset($data['friendIdOrGroupId']) ? intval($data['friendIdOrGroupId']) : 0;
$remarks = isset($data['remarks']) ? $data['remarks'] : '';
$companyId = isset($data['companyId']) ? intval($data['companyId']) : $this->getUserInfo('companyId');
$userId = isset($data['userId']) ? intval($data['userId']) : $this->getUserInfo('id');
// 验证必要参数
if ($tokens <= 0) {
return ResponseHelper::error('tokens数量必须大于0');
}
if (!in_array($type, [0, 1])) {
return ResponseHelper::error('类型参数错误0为减少1为增加');
}
if (!in_array($form, [0, 1, 2, 3, 4, 5])) {
return ResponseHelper::error('来源参数错误');
}
// 重试机制最多重试3次
$maxRetries = 3;
$retryCount = 0;
while ($retryCount < $maxRetries) {
try {
return $this->doConsumeTokens($userId, $companyId, $tokens, $type, $form, $wechatAccountId, $friendIdOrGroupId, $remarks);
} catch (\Exception $e) {
$retryCount++;
if ($retryCount >= $maxRetries) {
return ResponseHelper::error('操作失败,请稍后重试:' . $e->getMessage());
}
// 短暂延迟后重试
usleep(100000); // 100ms
}
}
}
/**
* 执行tokens消费的核心方法
*/
private function doConsumeTokens($userId, $companyId, $tokens, $type, $form, $wechatAccountId, $friendIdOrGroupId, $remarks)
{
// 开启数据库事务
Db::startTrans();
try {
// 使用悲观锁获取用户当前tokens余额确保并发安全
$userInfo = Db::name('users')
->where('id', $userId)
->where('companyId', $companyId)
->lock(true) // 悲观锁,防止并发问题
->find();
if (!$userInfo) {
throw new \Exception('用户不存在');
}
$currentTokens = intval($userInfo['tokens']);
// 计算新的余额
$newBalance = $type == 1 ? ($currentTokens + $tokens) : ($currentTokens - $tokens);
// 使用原子更新操作,基于当前值进行更新,防止并发覆盖
$updateResult = Db::name('users')
->where('id', $userId)
->where('companyId', $companyId)
->where('tokens', $currentTokens) // 确保基于当前值更新
->update([
'tokens' => $newBalance,
'updateTime' => time()
]);
if (!$updateResult) {
// 如果更新失败说明tokens值已被其他事务修改需要重新获取
throw new \Exception('tokens余额已被其他操作修改请重试');
}
// 记录tokens变动
$recordData = [
'companyId' => $companyId,
'userId' => $userId,
'wechatAccountId' => $wechatAccountId,
'friendIdOrGroupId' => $friendIdOrGroupId,
'form' => $form,
'type' => $type,
'tokens' => $tokens,
'balanceTokens' => $newBalance,
'remarks' => $remarks,
'createTime' => time()
];
$recordId = Db::name('tokens_record')->insertGetId($recordData);
if (!$recordId) {
throw new \Exception('记录tokens变动失败');
}
// 提交事务
Db::commit();
return ResponseHelper::success([
'recordId' => $recordId,
'oldBalance' => $currentTokens,
'newBalance' => $newBalance,
'changeAmount' => $type == 1 ? $tokens : -$tokens
], 'tokens变动记录成功');
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
throw $e; // 重新抛出异常,让重试机制处理
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace app\chukebao\model;
use think\Model;
class TokensRecord extends Model
{
protected $pk = 'id';
protected $name = 'tokens_record';
// 自动写入时间戳
protected $autoWriteTimestamp = true;
protected $createTime = 'createTime';
}