修复充值
This commit is contained in:
parent
1c5a38ad73
commit
f18dd7a470
31
src/Oms.Application/Dtos/Recharge/SubmitRechargeFormInput.cs
Normal file
31
src/Oms.Application/Dtos/Recharge/SubmitRechargeFormInput.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Oms.Domain.RechargeAggregate.Enums;
|
||||||
|
|
||||||
|
namespace Oms.Application.Dtos.Recharge;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值提交入参(multipart/form-data,截图字段名为 rechargeScreenshot)。
|
||||||
|
/// </summary>
|
||||||
|
public class SubmitRechargeFormInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 客户主键(t_customer.Id)。
|
||||||
|
/// </summary>
|
||||||
|
public int? CustomerId { get; set; }
|
||||||
|
|
||||||
|
[Range(typeof(decimal), "0.01", "999999999999")]
|
||||||
|
public decimal RechargeAmount { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public PayType PayType { get; set; }
|
||||||
|
|
||||||
|
[StringLength(512)]
|
||||||
|
public string? Remark { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 充值截图文件。
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public IFormFile RechargeScreenshot { get; set; } = null!;
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using Fake.Application;
|
using Fake.Application;
|
||||||
|
using Fake.Domain.Exceptions;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MiniExcelLibs;
|
using MiniExcelLibs;
|
||||||
using Oms.Application.Dtos.Recharge;
|
using Oms.Application.Dtos.Recharge;
|
||||||
@ -17,20 +19,16 @@ public class RechargeService : ApplicationService
|
|||||||
{
|
{
|
||||||
private IRechargeRecordRepository RechargeRecordRepository => LazyServiceProvider.GetRequiredService<IRechargeRecordRepository>();
|
private IRechargeRecordRepository RechargeRecordRepository => LazyServiceProvider.GetRequiredService<IRechargeRecordRepository>();
|
||||||
private ICustomerRepository CustomerRepository => LazyServiceProvider.GetRequiredService<ICustomerRepository>();
|
private ICustomerRepository CustomerRepository => LazyServiceProvider.GetRequiredService<ICustomerRepository>();
|
||||||
|
private IWebHostEnvironment WebHostEnvironment => LazyServiceProvider.GetRequiredService<IWebHostEnvironment>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提交充值申请。
|
/// 提交充值申请。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">入参:充值提交参数。</param>
|
/// <param name="input">入参:multipart 表单,截图字段 rechargeScreenshot。</param>
|
||||||
/// <returns>充值记录结果。</returns>
|
/// <returns>充值记录结果。</returns>
|
||||||
/// <remarks>
|
|
||||||
/// 核心业务逻辑:
|
|
||||||
/// 1. 校验入参与关联对象、唯一性等前置条件。
|
|
||||||
/// 2. 组装目标实体及相关明细数据。
|
|
||||||
/// 3. 写入审计字段并持久化结果。
|
|
||||||
/// </remarks>
|
|
||||||
[HttpPost("/recharge/recharge/submit")]
|
[HttpPost("/recharge/recharge/submit")]
|
||||||
public async Task<RechargeRecordOutput> SubmitAsync(SubmitRechargeInput input)
|
[Consumes("multipart/form-data")]
|
||||||
|
public async Task<RechargeRecordOutput> SubmitAsync([FromForm] SubmitRechargeFormInput input)
|
||||||
{
|
{
|
||||||
var customerId = input.CustomerId ?? CurrentUser.GetId<int>();
|
var customerId = input.CustomerId ?? CurrentUser.GetId<int>();
|
||||||
if (customerId <= 0)
|
if (customerId <= 0)
|
||||||
@ -44,6 +42,15 @@ public class RechargeService : ApplicationService
|
|||||||
throw new BusinessException("客户不存在");
|
throw new BusinessException("客户不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.RechargeAmount < 0.01M)
|
||||||
|
{
|
||||||
|
throw new BusinessException("充值金额不能小于 0.01");
|
||||||
|
}
|
||||||
|
|
||||||
|
var screenshotPath = await OmsFileUploadHelper.SaveRechargeScreenshotAsync(
|
||||||
|
input.RechargeScreenshot,
|
||||||
|
WebHostEnvironment);
|
||||||
|
|
||||||
var entity = new RechargeRecord
|
var entity = new RechargeRecord
|
||||||
{
|
{
|
||||||
CustomerId = customer.Id,
|
CustomerId = customer.Id,
|
||||||
@ -51,7 +58,7 @@ public class RechargeService : ApplicationService
|
|||||||
RechargeTime = DateTime.Now,
|
RechargeTime = DateTime.Now,
|
||||||
PayType = input.PayType,
|
PayType = input.PayType,
|
||||||
RechargeAmount = input.RechargeAmount,
|
RechargeAmount = input.RechargeAmount,
|
||||||
RechargeScreenshot = input.RechargeScreenshot,
|
RechargeScreenshot = screenshotPath,
|
||||||
RechargeStatus = RechargeStatus.Pending,
|
RechargeStatus = RechargeStatus.Pending,
|
||||||
Remark = input.Remark
|
Remark = input.Remark
|
||||||
};
|
};
|
||||||
|
|||||||
73
src/Oms.Application/Shared/OmsFileUploadHelper.cs
Normal file
73
src/Oms.Application/Shared/OmsFileUploadHelper.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using Fake.Domain.Exceptions;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace Oms.Application.Shared;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OMS 上传文件落盘(wwwroot/uploads)。
|
||||||
|
/// </summary>
|
||||||
|
public static class OmsFileUploadHelper
|
||||||
|
{
|
||||||
|
private static readonly HashSet<string> ImageExtensions =
|
||||||
|
new(StringComparer.OrdinalIgnoreCase) { ".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp" };
|
||||||
|
|
||||||
|
private const long MaxImageBytes = 5 * 1024 * 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存充值截图,返回以 /uploads 开头的相对访问路径。
|
||||||
|
/// </summary>
|
||||||
|
public static async Task<string> SaveRechargeScreenshotAsync(IFormFile file, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
if (file == null || file.Length <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException("请上传充值截图");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.Length > MaxImageBytes)
|
||||||
|
{
|
||||||
|
throw new BusinessException("充值截图大小不能超过 5MB");
|
||||||
|
}
|
||||||
|
|
||||||
|
var ext = Path.GetExtension(file.FileName);
|
||||||
|
if (string.IsNullOrWhiteSpace(ext) || !ImageExtensions.Contains(ext))
|
||||||
|
{
|
||||||
|
ext = GuessExtensionFromContentType(file.ContentType) ?? ".jpg";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImageExtensions.Contains(ext))
|
||||||
|
{
|
||||||
|
throw new BusinessException("充值截图仅支持 jpg、png、webp、gif、bmp 格式");
|
||||||
|
}
|
||||||
|
|
||||||
|
var webRoot = env.WebRootPath;
|
||||||
|
if (string.IsNullOrWhiteSpace(webRoot))
|
||||||
|
{
|
||||||
|
webRoot = Path.Combine(env.ContentRootPath, "wwwroot");
|
||||||
|
}
|
||||||
|
|
||||||
|
var monthFolder = DateTime.Now.ToString("yyyyMM");
|
||||||
|
var relativeDir = Path.Combine("uploads", "recharge", monthFolder);
|
||||||
|
var absoluteDir = Path.Combine(webRoot, relativeDir);
|
||||||
|
Directory.CreateDirectory(absoluteDir);
|
||||||
|
|
||||||
|
var fileName = $"{Guid.NewGuid():N}{ext.ToLowerInvariant()}";
|
||||||
|
var absolutePath = Path.Combine(absoluteDir, fileName);
|
||||||
|
await using (var stream = File.Create(absolutePath))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"/uploads/recharge/{monthFolder}/{fileName}".Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? GuessExtensionFromContentType(string? contentType) => contentType?.ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"image/jpeg" or "image/jpg" => ".jpg",
|
||||||
|
"image/png" => ".png",
|
||||||
|
"image/webp" => ".webp",
|
||||||
|
"image/gif" => ".gif",
|
||||||
|
"image/bmp" => ".bmp",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user