using System.ComponentModel.DataAnnotations; using System.Text.Json; using MAX.Framework.Commons; using MAX.Framework.Validation; using Store.Shops.Dtos; using Store.Shops.Entities; namespace Store.Shops.Services; public sealed partial class ShopService { /// 获取当前用户授权店铺的微信令牌,外部请求不在数据库事务中执行。 public async Task ShopToken(ShopIdRequest request, CancellationToken ct) { RequestValidator.Validate(request); var actor = await Actor(); await RequireShop(db, actor, request.ShopId, ct); return await tokens.GetShopToken(request.ShopId, ct); } /// 管理员读取共享令牌列表;缓存有效期60分钟,配置按缓存ID指定e57账号。 public async Task TokenList(TokenRequest request, CancellationToken ct) { RequestValidator.Validate(request); if (request.DbId <= 0) throw new ValidationException("缓存记录ID必须大于0"); RequireAdmin(await Actor()); var cached = await db.Select().Where(t => t.Id == request.DbId).FirstAsync(ct); if (cached != null && cached.MdyTime.AddMinutes(60) > DateTime.Now) { try { using var json = JsonDocument.Parse(cached.Tokens); if (json.RootElement.ValueKind == JsonValueKind.Array) return new(json.RootElement.Clone(), cached.MdyTime); } catch (JsonException) { /* 旧缓存损坏时重新向上游获取,不返回无法解析的数据。 */ } } var account = configuration[$"Shops:E57WxAccounts:{request.DbId}"]; if (string.IsNullOrWhiteSpace(account)) throw new AppException("尚未配置该缓存分组的e57微信账号"); var list = await tokens.GetTokens(account, ct); if (list.ValueKind != JsonValueKind.Array) throw new AppException("e57返回的令牌列表格式无效"); var now = DateTime.Now; using var work = db.CreateUnitOfWork(); work.IsolationLevel = System.Data.IsolationLevel.Serializable; work.GetOrBeginTransaction(); var orm = work.Orm; var existing = await orm.Select().Where(t => t.Id == request.DbId).ForUpdate().FirstAsync(ct); if (existing == null) await orm.Insert(new TokenEntity { Id = request.DbId, Tokens = list.GetRawText(), MdyTime = now }).ExecuteAffrowsAsync(ct); else await orm.Update().Where(t => t.Id == request.DbId) .Set(t => t.Tokens, list.GetRawText()).Set(t => t.MdyTime, now).ExecuteAffrowsAsync(ct); ct.ThrowIfCancellationRequested(); work.Commit(); return new(list, now); } }