using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Tiku.Api.Contracts; using Tiku.Application.Commerce; using Tiku.Application.Security; namespace Tiku.Api.Controllers; [ApiController] [Authorize(Policy = TikuPolicies.TenantAdmin)] [Produces("application/json")] [Route("api/tenant-commerce")] public sealed class TenantCommerceController( ICommerceAdminService commerceAdminService, ICurrentUser currentUser, ICurrentTenant currentTenant) : ControllerBase { [HttpGet("payment-accounts")] [EndpointSummary("查询租户支付账号")] [ProducesResponseType>(StatusCodes.Status200OK)] public async Task>> PaymentAccounts( [FromQuery] TenantCommerceQueryDto query, CancellationToken cancellationToken) { return Ok(await commerceAdminService.GetPaymentAccountsAsync( ResolveActor(), ToQuery(query), cancellationToken)); } [HttpPut("payment-accounts")] [EndpointSummary("新增或更新租户支付账号")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> UpsertPaymentAccount( UpsertPaymentAccountDto request, CancellationToken cancellationToken) { return Ok(await commerceAdminService.UpsertPaymentAccountAsync( ResolveActor(), request.ToCommand(), cancellationToken)); } [HttpPut("secrets")] [EndpointSummary("写入或轮换租户密钥")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> UpsertSecret( UpsertTenantSecretDto request, CancellationToken cancellationToken) { return Ok(await commerceAdminService.UpsertTenantSecretAsync( ResolveActor(), request.ToCommand(), cancellationToken)); } [HttpGet("orders")] [EndpointSummary("查询租户订单")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Orders( [FromQuery] TenantCommerceQueryDto query, CancellationToken cancellationToken) { return Ok(await commerceAdminService.GetOrdersAsync( ResolveActor(), ToQuery(query), cancellationToken)); } [HttpGet("payments")] [EndpointSummary("查询租户支付记录")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Payments( [FromQuery] TenantCommerceQueryDto query, CancellationToken cancellationToken) { return Ok(await commerceAdminService.GetPaymentsAsync( ResolveActor(), ToQuery(query), cancellationToken)); } [HttpPost("code-batches")] [EndpointSummary("创建兑换码批次")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> CreateCodeBatch( CreateCodeBatchDto request, CancellationToken cancellationToken) { return Ok(await commerceAdminService.CreateCodeBatchAsync( ResolveActor(), request.ToCommand(), cancellationToken)); } [HttpGet("activation-codes")] [EndpointSummary("查询兑换码")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> ActivationCodes( [FromQuery] TenantCommerceQueryDto query, CancellationToken cancellationToken) { return Ok(await commerceAdminService.GetActivationCodesAsync( ResolveActor(), ToQuery(query), cancellationToken)); } [HttpPost("activation-codes/redeem")] [EndpointSummary("后台核销兑换码")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> RedeemActivationCode( RedeemActivationCodeDto request, CancellationToken cancellationToken) { return Ok(await commerceAdminService.RedeemActivationCodeAsync( ResolveActor(), request.ToCommand(), cancellationToken)); } private CommerceAdminActor ResolveActor() { if (currentTenant.TenantId is null || currentUser.UserId is null) { throw new CommerceException("Tenant commerce actor was not resolved.", "tenant_admin_access_denied"); } return new CommerceAdminActor(currentTenant.TenantId.Value, currentUser.UserId.Value); } private static CommerceAdminQuery ToQuery(TenantCommerceQueryDto query) { return new CommerceAdminQuery(query.Provider, query.Status, query.Limit); } }