91 lines
3.4 KiB
C#
91 lines
3.4 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using TakeoutSaaS.AdminApi.Contracts.Responses;
|
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
|
using TakeoutSaaS.Shared.Web.Api;
|
|
|
|
namespace TakeoutSaaS.AdminApi.Controllers;
|
|
|
|
/// <summary>
|
|
/// 腾讯地图脚本签名服务。
|
|
/// </summary>
|
|
[ApiVersion("1.0")]
|
|
[Authorize]
|
|
[Route("api/admin/v{version:apiVersion}/maps")]
|
|
public sealed class TencentMapsController(IConfiguration configuration) : BaseApiController
|
|
{
|
|
private const string DefaultLibraries = "visualization,geometry,vector,tools";
|
|
private const string DefaultCallback = "initGLMap";
|
|
private const string DefaultVersion = "1.exp";
|
|
|
|
/// <summary>
|
|
/// 获取腾讯地图 JS 脚本地址(含签名)。
|
|
/// </summary>
|
|
[HttpGet("tencent-js")]
|
|
[ProducesResponseType(typeof(ApiResponse<TencentMapScriptResponse>), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
|
|
public ApiResponse<TencentMapScriptResponse> GetTencentJsScript(
|
|
[FromQuery] string? libraries,
|
|
[FromQuery] string? callback,
|
|
[FromQuery] string? v)
|
|
{
|
|
// 1. 读取配置
|
|
var key = configuration.GetValue<string>("TencentMap:Key");
|
|
var sk = configuration.GetValue<string>("TencentMap:Sk");
|
|
if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(sk))
|
|
{
|
|
return ApiResponse<TencentMapScriptResponse>.Error(ErrorCodes.BadRequest, "未配置腾讯地图 Key/SK");
|
|
}
|
|
|
|
// 2. 规范化参数
|
|
var resolvedLibraries = string.IsNullOrWhiteSpace(libraries) ? DefaultLibraries : libraries;
|
|
var resolvedCallback = string.IsNullOrWhiteSpace(callback) ? DefaultCallback : callback;
|
|
var resolvedVersion = string.IsNullOrWhiteSpace(v) ? DefaultVersion : v;
|
|
|
|
// 3. 构建签名
|
|
var parameters = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
|
{
|
|
["callback"] = resolvedCallback,
|
|
["key"] = key,
|
|
["libraries"] = resolvedLibraries,
|
|
["v"] = resolvedVersion
|
|
};
|
|
var queryString = BuildQueryString(parameters);
|
|
var signature = ComputeSignature("/api/gljs", queryString, sk);
|
|
var scriptUrl = $"https://map.qq.com/api/gljs?{queryString}&sig={signature}";
|
|
|
|
return ApiResponse<TencentMapScriptResponse>.Ok(new TencentMapScriptResponse(scriptUrl));
|
|
}
|
|
|
|
private static string BuildQueryString(IEnumerable<KeyValuePair<string, string>> parameters)
|
|
{
|
|
var builder = new StringBuilder();
|
|
foreach (var (key, value) in parameters)
|
|
{
|
|
if (builder.Length > 0)
|
|
{
|
|
builder.Append('&');
|
|
}
|
|
builder.Append(key);
|
|
builder.Append('=');
|
|
builder.Append(Uri.EscapeDataString(value));
|
|
}
|
|
return builder.ToString();
|
|
}
|
|
|
|
private static string ComputeSignature(string path, string queryString, string sk)
|
|
{
|
|
var raw = $"{path}?{queryString}{sk}";
|
|
var hash = MD5.HashData(Encoding.UTF8.GetBytes(raw));
|
|
var builder = new StringBuilder(hash.Length * 2);
|
|
foreach (var b in hash)
|
|
{
|
|
builder.Append(b.ToString("x2"));
|
|
}
|
|
return builder.ToString();
|
|
}
|
|
}
|