feat: 店铺平台 OAuth 配置迁入其他配置页
运行时优先读 t_system_other_config,修正管理端客户提示文案,并提供配置种子 SQL。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
674cbdd011
commit
c2c03f63e3
47
sql/seed_platform_shop_other_config.sql
Normal file
47
sql/seed_platform_shop_other_config.sql
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
-- 店铺平台 OAuth 配置种子(其他配置页可改;已存在则跳过)
|
||||||
|
INSERT INTO t_system_other_config
|
||||||
|
(ConfigCode, ConfigName, Enabled, BaseUrl, AppKey, AppSecret, TimeoutSeconds, Remark, IsDeleted, CreateTime)
|
||||||
|
SELECT 'platform_shop', '店铺授权-公共', 1, 'http://localhost:5173', NULL, NULL, 30, NULL, 0, NOW()
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM t_system_other_config WHERE ConfigCode = 'platform_shop' AND IsDeleted = 0);
|
||||||
|
|
||||||
|
INSERT INTO t_system_other_config
|
||||||
|
(ConfigCode, ConfigName, Enabled, BaseUrl, AppKey, AppSecret, TimeoutSeconds, Remark, IsDeleted, CreateTime)
|
||||||
|
SELECT 'platform_shop_tiktok', '店铺授权-TikTok', 1,
|
||||||
|
'https://auth.tiktok-shops.com',
|
||||||
|
'6hc64lc6vl312',
|
||||||
|
'5a691a96ee6d844534769bab5c21de1f848fb678',
|
||||||
|
30,
|
||||||
|
'https://open-api.tiktokglobalshop.com',
|
||||||
|
0, NOW()
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM t_system_other_config WHERE ConfigCode = 'platform_shop_tiktok' AND IsDeleted = 0);
|
||||||
|
|
||||||
|
INSERT INTO t_system_other_config
|
||||||
|
(ConfigCode, ConfigName, Enabled, BaseUrl, AppKey, AppSecret, TimeoutSeconds, Remark, IsDeleted, CreateTime)
|
||||||
|
SELECT 'platform_shop_temu', '店铺授权-Temu', 1,
|
||||||
|
'https://openapi-b-us.temu.com/openapi/router',
|
||||||
|
'4ebbc9190ae410443d65b4c2faca981f',
|
||||||
|
'4782d2d827276688bf4758bed55dbdd4bbe79a79',
|
||||||
|
30, NULL, 0, NOW()
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM t_system_other_config WHERE ConfigCode = 'platform_shop_temu' AND IsDeleted = 0);
|
||||||
|
|
||||||
|
INSERT INTO t_system_other_config
|
||||||
|
(ConfigCode, ConfigName, Enabled, BaseUrl, AppKey, AppSecret, TimeoutSeconds, Remark, IsDeleted, CreateTime)
|
||||||
|
SELECT 'platform_shop_shopee', '店铺授权-Shopee', 1,
|
||||||
|
'https://partner.shopeemobile.com',
|
||||||
|
'2004112',
|
||||||
|
'2f385d7ea38b087d5d71f7292e06a09c9f19022ca6c3f60ec0110a8214ef7d65',
|
||||||
|
30,
|
||||||
|
'https://openplatform.shopee.cn',
|
||||||
|
0, NOW()
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM t_system_other_config WHERE ConfigCode = 'platform_shop_shopee' AND IsDeleted = 0);
|
||||||
|
|
||||||
|
INSERT INTO t_system_other_config
|
||||||
|
(ConfigCode, ConfigName, Enabled, BaseUrl, AppKey, AppSecret, TimeoutSeconds, Remark, IsDeleted, CreateTime)
|
||||||
|
SELECT 'platform_shop_lazada', '店铺授权-Lazada', 1,
|
||||||
|
'https://auth.lazada.com/oauth/authorize',
|
||||||
|
'123631',
|
||||||
|
'7vBz2EaD6rIupeGEfwrgkabsTNsXt2ix',
|
||||||
|
30,
|
||||||
|
'https://auth.lazada.com/rest',
|
||||||
|
0, NOW()
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM t_system_other_config WHERE ConfigCode = 'platform_shop_lazada' AND IsDeleted = 0);
|
||||||
@ -2,13 +2,12 @@ using System.Net.Http.Json;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
namespace Oms.Application.Integrations.PlatformShop;
|
namespace Oms.Application.Integrations.PlatformShop;
|
||||||
|
|
||||||
public interface IPlatformShopApiClient
|
public interface IPlatformShopApiClient
|
||||||
{
|
{
|
||||||
string BuildAuthUrl(string platformCode, string redirectUri, string state, string? siteCountry);
|
Task<string> BuildAuthUrlAsync(string platformCode, string redirectUri, string state, string? siteCountry, CancellationToken ct = default);
|
||||||
Task<PlatformShopTokenResult> ExchangeTokenAsync(PlatformShopTokenExchangeRequest request, CancellationToken ct = default);
|
Task<PlatformShopTokenResult> ExchangeTokenAsync(PlatformShopTokenExchangeRequest request, CancellationToken ct = default);
|
||||||
Task<PlatformShopTokenResult> CreateTemuStoreTokenAsync(string authorizationCode, CancellationToken ct = default);
|
Task<PlatformShopTokenResult> CreateTemuStoreTokenAsync(string authorizationCode, CancellationToken ct = default);
|
||||||
}
|
}
|
||||||
@ -45,15 +44,26 @@ public sealed class PlatformShopBoundShop
|
|||||||
|
|
||||||
internal sealed class PlatformShopApiClient(
|
internal sealed class PlatformShopApiClient(
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
IOptions<PlatformShopOptions> options,
|
IPlatformShopConfigProvider configProvider,
|
||||||
ILogger<PlatformShopApiClient> logger) : IPlatformShopApiClient
|
ILogger<PlatformShopApiClient> logger) : IPlatformShopApiClient
|
||||||
{
|
{
|
||||||
public const string HttpClientName = nameof(PlatformShopApiClient);
|
public const string HttpClientName = nameof(PlatformShopApiClient);
|
||||||
|
|
||||||
private readonly PlatformShopOptions _options = options.Value;
|
private PlatformShopOptions _options = new();
|
||||||
|
|
||||||
public string BuildAuthUrl(string platformCode, string redirectUri, string state, string? siteCountry)
|
private async Task LoadOptionsAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
|
_options = await configProvider.GetAsync(ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> BuildAuthUrlAsync(
|
||||||
|
string platformCode,
|
||||||
|
string redirectUri,
|
||||||
|
string state,
|
||||||
|
string? siteCountry,
|
||||||
|
CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
await LoadOptionsAsync(ct);
|
||||||
return platformCode.ToLowerInvariant() switch
|
return platformCode.ToLowerInvariant() switch
|
||||||
{
|
{
|
||||||
"lazada" => BuildLazadaAuthUrl(redirectUri, siteCountry),
|
"lazada" => BuildLazadaAuthUrl(redirectUri, siteCountry),
|
||||||
@ -67,6 +77,7 @@ internal sealed class PlatformShopApiClient(
|
|||||||
PlatformShopTokenExchangeRequest request,
|
PlatformShopTokenExchangeRequest request,
|
||||||
CancellationToken ct = default)
|
CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
|
await LoadOptionsAsync(ct);
|
||||||
return request.PlatformCode.ToLowerInvariant() switch
|
return request.PlatformCode.ToLowerInvariant() switch
|
||||||
{
|
{
|
||||||
"lazada" => await ExchangeLazadaAsync(request.Code, ct),
|
"lazada" => await ExchangeLazadaAsync(request.Code, ct),
|
||||||
@ -78,6 +89,7 @@ internal sealed class PlatformShopApiClient(
|
|||||||
|
|
||||||
public async Task<PlatformShopTokenResult> CreateTemuStoreTokenAsync(string authorizationCode, CancellationToken ct = default)
|
public async Task<PlatformShopTokenResult> CreateTemuStoreTokenAsync(string authorizationCode, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
|
await LoadOptionsAsync(ct);
|
||||||
EnsureTemuConfigured();
|
EnsureTemuConfigured();
|
||||||
var temu = _options.Temu;
|
var temu = _options.Temu;
|
||||||
var body = new Dictionary<string, string>
|
var body = new Dictionary<string, string>
|
||||||
|
|||||||
@ -0,0 +1,147 @@
|
|||||||
|
using Fake.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Oms.Domain.SystemAggregate.Consts;
|
||||||
|
using Oms.Domain.SystemAggregate.Entities;
|
||||||
|
using Oms.Domain.SystemAggregate.Repositories;
|
||||||
|
|
||||||
|
namespace Oms.Application.Integrations.PlatformShop;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 平台店铺 OAuth 运行时配置:优先读「其他配置」,回退 appsettings。
|
||||||
|
/// </summary>
|
||||||
|
public interface IPlatformShopConfigProvider
|
||||||
|
{
|
||||||
|
Task<PlatformShopOptions> GetAsync(CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class PlatformShopConfigProvider(
|
||||||
|
ISystemOtherConfigRepository repository,
|
||||||
|
IOptions<PlatformShopOptions> options) : IPlatformShopConfigProvider, IScopedDependency
|
||||||
|
{
|
||||||
|
public async Task<PlatformShopOptions> GetAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var fallback = options.Value ?? new PlatformShopOptions();
|
||||||
|
var common = await repository.GetByConfigCodeAsync(SystemOtherConfigCodes.PlatformShop, cancellationToken);
|
||||||
|
var lazada = await repository.GetByConfigCodeAsync(SystemOtherConfigCodes.PlatformShopLazada, cancellationToken);
|
||||||
|
var shopee = await repository.GetByConfigCodeAsync(SystemOtherConfigCodes.PlatformShopShopee, cancellationToken);
|
||||||
|
var tiktok = await repository.GetByConfigCodeAsync(SystemOtherConfigCodes.PlatformShopTiktok, cancellationToken);
|
||||||
|
var temu = await repository.GetByConfigCodeAsync(SystemOtherConfigCodes.PlatformShopTemu, cancellationToken);
|
||||||
|
|
||||||
|
return new PlatformShopOptions
|
||||||
|
{
|
||||||
|
FrontendBaseUrl = Coalesce(common?.BaseUrl, fallback.FrontendBaseUrl),
|
||||||
|
StateSecret = Coalesce(common?.Remark, fallback.StateSecret),
|
||||||
|
Lazada = MergeLazada(lazada, fallback.Lazada),
|
||||||
|
Shopee = MergeShopee(shopee, fallback.Shopee),
|
||||||
|
Tiktok = MergeTiktok(tiktok, fallback.Tiktok),
|
||||||
|
Temu = MergeTemu(temu, fallback.Temu)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LazadaPlatformOptions MergeLazada(SystemOtherConfig? entity, LazadaPlatformOptions fallback)
|
||||||
|
{
|
||||||
|
fallback ??= new LazadaPlatformOptions();
|
||||||
|
if (entity == null || !entity.Enabled)
|
||||||
|
{
|
||||||
|
return CloneLazada(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LazadaPlatformOptions
|
||||||
|
{
|
||||||
|
AppKey = Coalesce(entity.AppKey, fallback.AppKey),
|
||||||
|
AppSecret = Coalesce(entity.AppSecret, fallback.AppSecret),
|
||||||
|
AuthorizeUrl = Coalesce(entity.BaseUrl, fallback.AuthorizeUrl),
|
||||||
|
AccessTokenUrl = Coalesce(entity.Remark, fallback.AccessTokenUrl)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ShopeePlatformOptions MergeShopee(SystemOtherConfig? entity, ShopeePlatformOptions fallback)
|
||||||
|
{
|
||||||
|
fallback ??= new ShopeePlatformOptions();
|
||||||
|
if (entity == null || !entity.Enabled)
|
||||||
|
{
|
||||||
|
return CloneShopee(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
var partnerId = fallback.PartnerId;
|
||||||
|
if (int.TryParse(entity.AppKey?.Trim(), out var parsed) && parsed > 0)
|
||||||
|
{
|
||||||
|
partnerId = parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ShopeePlatformOptions
|
||||||
|
{
|
||||||
|
PartnerId = partnerId,
|
||||||
|
PartnerKey = Coalesce(entity.AppSecret, fallback.PartnerKey),
|
||||||
|
HostAuthUrl = Coalesce(entity.BaseUrl, fallback.HostAuthUrl),
|
||||||
|
HostUrl = Coalesce(entity.Remark, fallback.HostUrl)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TiktokPlatformOptions MergeTiktok(SystemOtherConfig? entity, TiktokPlatformOptions fallback)
|
||||||
|
{
|
||||||
|
fallback ??= new TiktokPlatformOptions();
|
||||||
|
if (entity == null || !entity.Enabled)
|
||||||
|
{
|
||||||
|
return CloneTiktok(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TiktokPlatformOptions
|
||||||
|
{
|
||||||
|
AppKey = Coalesce(entity.AppKey, fallback.AppKey),
|
||||||
|
AppSecret = Coalesce(entity.AppSecret, fallback.AppSecret),
|
||||||
|
HostAuth = Coalesce(entity.BaseUrl, fallback.HostAuth),
|
||||||
|
HostApi = Coalesce(entity.Remark, fallback.HostApi)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TemuPlatformOptions MergeTemu(SystemOtherConfig? entity, TemuPlatformOptions fallback)
|
||||||
|
{
|
||||||
|
fallback ??= new TemuPlatformOptions();
|
||||||
|
if (entity == null || !entity.Enabled)
|
||||||
|
{
|
||||||
|
return CloneTemu(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TemuPlatformOptions
|
||||||
|
{
|
||||||
|
AppKey = Coalesce(entity.AppKey, fallback.AppKey),
|
||||||
|
AppSecret = Coalesce(entity.AppSecret, fallback.AppSecret),
|
||||||
|
HostAuthUrl = Coalesce(entity.BaseUrl, fallback.HostAuthUrl)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LazadaPlatformOptions CloneLazada(LazadaPlatformOptions src) => new()
|
||||||
|
{
|
||||||
|
AppKey = src.AppKey,
|
||||||
|
AppSecret = src.AppSecret,
|
||||||
|
AuthorizeUrl = src.AuthorizeUrl,
|
||||||
|
AccessTokenUrl = src.AccessTokenUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
private static ShopeePlatformOptions CloneShopee(ShopeePlatformOptions src) => new()
|
||||||
|
{
|
||||||
|
PartnerId = src.PartnerId,
|
||||||
|
PartnerKey = src.PartnerKey,
|
||||||
|
HostUrl = src.HostUrl,
|
||||||
|
HostAuthUrl = src.HostAuthUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
private static TiktokPlatformOptions CloneTiktok(TiktokPlatformOptions src) => new()
|
||||||
|
{
|
||||||
|
AppKey = src.AppKey,
|
||||||
|
AppSecret = src.AppSecret,
|
||||||
|
HostAuth = src.HostAuth,
|
||||||
|
HostApi = src.HostApi
|
||||||
|
};
|
||||||
|
|
||||||
|
private static TemuPlatformOptions CloneTemu(TemuPlatformOptions src) => new()
|
||||||
|
{
|
||||||
|
AppKey = src.AppKey,
|
||||||
|
AppSecret = src.AppSecret,
|
||||||
|
HostAuthUrl = src.HostAuthUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
private static string Coalesce(string? primary, string? fallback) =>
|
||||||
|
!string.IsNullOrWhiteSpace(primary) ? primary.Trim() : (fallback ?? string.Empty);
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@ public static class PlatformShopServiceExtensions
|
|||||||
{
|
{
|
||||||
client.Timeout = TimeSpan.FromSeconds(60);
|
client.Timeout = TimeSpan.FromSeconds(60);
|
||||||
});
|
});
|
||||||
|
services.AddScoped<IPlatformShopConfigProvider, PlatformShopConfigProvider>();
|
||||||
services.AddScoped<IPlatformShopApiClient, PlatformShopApiClient>();
|
services.AddScoped<IPlatformShopApiClient, PlatformShopApiClient>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ using System.Linq.Expressions;
|
|||||||
using Fake.Application;
|
using Fake.Application;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Oms.Application.Dtos.PlatformStore;
|
using Oms.Application.Dtos.PlatformStore;
|
||||||
using Oms.Application.Dtos.Shared;
|
using Oms.Application.Dtos.Shared;
|
||||||
using Oms.Application.Integrations.PlatformShop;
|
using Oms.Application.Integrations.PlatformShop;
|
||||||
@ -23,8 +22,8 @@ public class PlatformStoreService : ApplicationService
|
|||||||
private ICustomerRepository CustomerRepository => LazyServiceProvider.GetRequiredService<ICustomerRepository>();
|
private ICustomerRepository CustomerRepository => LazyServiceProvider.GetRequiredService<ICustomerRepository>();
|
||||||
private ISalesStoreRepository StoreRepository => LazyServiceProvider.GetRequiredService<ISalesStoreRepository>();
|
private ISalesStoreRepository StoreRepository => LazyServiceProvider.GetRequiredService<ISalesStoreRepository>();
|
||||||
private IPlatformShopApiClient PlatformShopApi => LazyServiceProvider.GetRequiredService<IPlatformShopApiClient>();
|
private IPlatformShopApiClient PlatformShopApi => LazyServiceProvider.GetRequiredService<IPlatformShopApiClient>();
|
||||||
private PlatformShopOptions PlatformShopOptions =>
|
private IPlatformShopConfigProvider PlatformShopConfig =>
|
||||||
LazyServiceProvider.GetRequiredService<IOptions<PlatformShopOptions>>().Value;
|
LazyServiceProvider.GetRequiredService<IPlatformShopConfigProvider>();
|
||||||
private IConfiguration Configuration => LazyServiceProvider.GetRequiredService<IConfiguration>();
|
private IConfiguration Configuration => LazyServiceProvider.GetRequiredService<IConfiguration>();
|
||||||
|
|
||||||
[HttpPost("/order/platform-store/list")]
|
[HttpPost("/order/platform-store/list")]
|
||||||
@ -71,7 +70,7 @@ public class PlatformStoreService : ApplicationService
|
|||||||
return platform switch
|
return platform switch
|
||||||
{
|
{
|
||||||
"temu" => await CreateTemuStoreAsync(customerId, nickname, input),
|
"temu" => await CreateTemuStoreAsync(customerId, nickname, input),
|
||||||
"lazada" or "shopee" or "tiktok" => BuildOAuthUrl(customerId, platform, nickname, input),
|
"lazada" or "shopee" or "tiktok" => await BuildOAuthUrlAsync(customerId, platform, nickname, input),
|
||||||
_ => throw new BusinessException($"暂不支持平台:{platform}")
|
_ => throw new BusinessException($"暂不支持平台:{platform}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -100,7 +99,13 @@ public class PlatformStoreService : ApplicationService
|
|||||||
|
|
||||||
var nickname = (input.StoreNickname ?? string.Empty).Trim();
|
var nickname = (input.StoreNickname ?? string.Empty).Trim();
|
||||||
var siteCountry = input.SiteCountry?.Trim();
|
var siteCountry = input.SiteCountry?.Trim();
|
||||||
var stateSecret = ResolveStateSecret();
|
var stateSecret = ResolveStateSecretFallback();
|
||||||
|
var shopOptions = await PlatformShopConfig.GetAsync();
|
||||||
|
if (!string.IsNullOrWhiteSpace(shopOptions.StateSecret))
|
||||||
|
{
|
||||||
|
stateSecret = shopOptions.StateSecret;
|
||||||
|
}
|
||||||
|
|
||||||
if (PlatformShopAuthState.TryDecode(input.State, stateSecret, out var statePayload)
|
if (PlatformShopAuthState.TryDecode(input.State, stateSecret, out var statePayload)
|
||||||
&& statePayload.CustomerId == customerId)
|
&& statePayload.CustomerId == customerId)
|
||||||
{
|
{
|
||||||
@ -277,16 +282,21 @@ public class PlatformStoreService : ApplicationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlatformStoreAuthUrlOutput BuildOAuthUrl(
|
private async Task<PlatformStoreAuthUrlOutput> BuildOAuthUrlAsync(
|
||||||
int customerId,
|
int customerId,
|
||||||
string platform,
|
string platform,
|
||||||
string nickname,
|
string nickname,
|
||||||
PlatformStoreAuthUrlInput input)
|
PlatformStoreAuthUrlInput input)
|
||||||
{
|
{
|
||||||
|
var shopOptions = await PlatformShopConfig.GetAsync();
|
||||||
var redirect = string.IsNullOrWhiteSpace(input.RedirectUri)
|
var redirect = string.IsNullOrWhiteSpace(input.RedirectUri)
|
||||||
? $"{PlatformShopOptions.FrontendBaseUrl.TrimEnd('/')}/oauth/platform-store/{platform}"
|
? $"{shopOptions.FrontendBaseUrl.TrimEnd('/')}/oauth/platform-store/{platform}"
|
||||||
: input.RedirectUri.Trim();
|
: input.RedirectUri.Trim();
|
||||||
|
|
||||||
|
var stateSecret = !string.IsNullOrWhiteSpace(shopOptions.StateSecret)
|
||||||
|
? shopOptions.StateSecret
|
||||||
|
: ResolveStateSecretFallback();
|
||||||
|
|
||||||
var state = PlatformShopAuthState.Encode(new PlatformShopAuthStatePayload
|
var state = PlatformShopAuthState.Encode(new PlatformShopAuthStatePayload
|
||||||
{
|
{
|
||||||
CustomerId = customerId,
|
CustomerId = customerId,
|
||||||
@ -294,11 +304,11 @@ public class PlatformStoreService : ApplicationService
|
|||||||
StoreNickname = nickname,
|
StoreNickname = nickname,
|
||||||
SiteCountry = input.SiteCountry?.Trim(),
|
SiteCountry = input.SiteCountry?.Trim(),
|
||||||
Exp = DateTimeOffset.UtcNow.AddHours(2).ToUnixTimeSeconds()
|
Exp = DateTimeOffset.UtcNow.AddHours(2).ToUnixTimeSeconds()
|
||||||
}, ResolveStateSecret());
|
}, stateSecret);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var authUrl = PlatformShopApi.BuildAuthUrl(platform, redirect, state, input.SiteCountry);
|
var authUrl = await PlatformShopApi.BuildAuthUrlAsync(platform, redirect, state, input.SiteCountry);
|
||||||
return new PlatformStoreAuthUrlOutput
|
return new PlatformStoreAuthUrlOutput
|
||||||
{
|
{
|
||||||
AuthUrl = authUrl,
|
AuthUrl = authUrl,
|
||||||
@ -374,13 +384,8 @@ public class PlatformStoreService : ApplicationService
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResolveStateSecret()
|
private string ResolveStateSecretFallback()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(PlatformShopOptions.StateSecret))
|
|
||||||
{
|
|
||||||
return PlatformShopOptions.StateSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Configuration["Jwt:SecretKey"]
|
return Configuration["Jwt:SecretKey"]
|
||||||
?? Configuration["JwtSettings:SecretKey"]
|
?? Configuration["JwtSettings:SecretKey"]
|
||||||
?? "oms-platform-shop-state-secret";
|
?? "oms-platform-shop-state-secret";
|
||||||
|
|||||||
@ -188,8 +188,44 @@ public class SystemOtherConfigService : ApplicationService
|
|||||||
throw new BusinessException("微信公众号 AppSecret 不能为空");
|
throw new BusinessException("微信公众号 AppSecret 不能为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (string.Equals(configCode, SystemOtherConfigCodes.PlatformShop, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.BaseUrl))
|
||||||
|
{
|
||||||
|
throw new BusinessException("店铺授权前端回调根地址不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsPlatformShopAppConfig(configCode))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input.AppKey))
|
||||||
|
{
|
||||||
|
throw new BusinessException("平台 AppKey / PartnerId 不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeId == null && ShouldKeepExistingSecret(input.AppSecret))
|
||||||
|
{
|
||||||
|
throw new BusinessException("平台 AppSecret / PartnerKey 不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(configCode, SystemOtherConfigCodes.PlatformShopShopee, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !int.TryParse(input.AppKey.Trim(), out _))
|
||||||
|
{
|
||||||
|
throw new BusinessException("Shopee PartnerId 必须为数字");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(input.BaseUrl))
|
||||||
|
{
|
||||||
|
throw new BusinessException("平台授权/API 地址不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsPlatformShopAppConfig(string configCode) =>
|
||||||
|
string.Equals(configCode, SystemOtherConfigCodes.PlatformShopLazada, StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(configCode, SystemOtherConfigCodes.PlatformShopShopee, StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(configCode, SystemOtherConfigCodes.PlatformShopTiktok, StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(configCode, SystemOtherConfigCodes.PlatformShopTemu, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private static SystemOtherConfigOutput MapOutput(SystemOtherConfig entity, bool maskSecret)
|
private static SystemOtherConfigOutput MapOutput(SystemOtherConfig entity, bool maskSecret)
|
||||||
{
|
{
|
||||||
return new SystemOtherConfigOutput
|
return new SystemOtherConfigOutput
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public static class WarehouseCustomerHelper
|
|||||||
var customerId = await ResolveListCustomerIdAsync(customerRepository, currentUser, requestedCustomerId);
|
var customerId = await ResolveListCustomerIdAsync(customerRepository, currentUser, requestedCustomerId);
|
||||||
if (!customerId.HasValue || customerId.Value <= 0)
|
if (!customerId.HasValue || customerId.Value <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("客户ID不能为空(管理端请先在「我的包裹」选择客户后再使用采集插件)");
|
throw new BusinessException("客户ID不能为空(管理端请先选择客户)");
|
||||||
}
|
}
|
||||||
|
|
||||||
return customerId.Value;
|
return customerId.Value;
|
||||||
|
|||||||
@ -14,4 +14,29 @@ public static class SystemOtherConfigCodes
|
|||||||
/// 微信公众号配置(AppKey=AppId,AppSecret=Secret,Remark=Token,BaseUrl=OAuthRedirectBase)。
|
/// 微信公众号配置(AppKey=AppId,AppSecret=Secret,Remark=Token,BaseUrl=OAuthRedirectBase)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string WeChatMp = "wechat_mp";
|
public const string WeChatMp = "wechat_mp";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 店铺授权公共配置(BaseUrl=前端回调根地址 FrontendBaseUrl,Remark=StateSecret 可选)。
|
||||||
|
/// </summary>
|
||||||
|
public const string PlatformShop = "platform_shop";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lazada(AppKey/AppSecret,BaseUrl=AuthorizeUrl,Remark=AccessTokenUrl)。
|
||||||
|
/// </summary>
|
||||||
|
public const string PlatformShopLazada = "platform_shop_lazada";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shopee(AppKey=PartnerId,AppSecret=PartnerKey,BaseUrl=HostAuthUrl,Remark=HostUrl)。
|
||||||
|
/// </summary>
|
||||||
|
public const string PlatformShopShopee = "platform_shop_shopee";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TikTok(AppKey/AppSecret,BaseUrl=HostAuth,Remark=HostApi)。
|
||||||
|
/// </summary>
|
||||||
|
public const string PlatformShopTiktok = "platform_shop_tiktok";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temu(AppKey/AppSecret,BaseUrl=HostAuthUrl)。
|
||||||
|
/// </summary>
|
||||||
|
public const string PlatformShopTemu = "platform_shop_temu";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user