using System.Text.Json; using MAX.Framework.Commons; namespace Store.Shops.Services; /// e57 店铺令牌查询;固定上游地址,失败重试一次,保留证书验证。 public sealed class PddTokenClient(HttpClient http) : IDisposable { /// 按拼多多商城ID获取授权资料。 public Task GetToken(string mallId, CancellationToken ct) => GetResult("info/forPdd?mallId=" + Uri.EscapeDataString(mallId), "data", ct); /// 按微信AppId获取单店授权资料。 public Task GetShopToken(string appId, CancellationToken ct) => GetResult("info?appId=" + Uri.EscapeDataString(appId), "data", ct); /// 按部署配置中的e57账号读取微信令牌列表。 public Task GetTokens(string userName, CancellationToken ct) => GetResult("list?userName=" + Uri.EscapeDataString(userName), "list", ct); /// 解析上游业务状态,只返回指定数据节点,不泄露原始错误页面。 private async Task GetResult(string path, string property, CancellationToken ct) { var url = "https://po.e57.cn/prod-api/api/sys-api/system/open/api/shop/" + path; for (var attempt = 0; attempt < 2; attempt++) { try { using var response = await http.GetAsync(url, ct); if (!response.IsSuccessStatusCode) continue; using var json = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync(ct), cancellationToken: ct); var root = json.RootElement; if (root.ValueKind == JsonValueKind.Object && root.TryGetProperty("code", out var code) && code.ValueKind == JsonValueKind.Number && code.TryGetInt32(out var value) && value == 0 && root.TryGetProperty(property, out var data)) return data.Clone(); } catch (HttpRequestException) { /* 上游网络失败按旧接口约定重试一次。 */ } catch (JsonException) { /* 非 JSON 上游响应按业务失败处理,不返回原始页面。 */ } catch (OperationCanceledException) when (!ct.IsCancellationRequested) { /* HttpClient 超时。 */ } } throw new AppException("获取店铺令牌失败,请稍后重试"); } /// 随容器关闭释放共享HTTP客户端。 public void Dispose() => http.Dispose(); }