fix: 微信注册软删除占坑与字段过长导致保存失败

fix: 微信注册软删除占坑与字段过长导致保存失败
This commit is contained in:
biybuy 2026-07-11 10:20:44 +08:00 committed by GitHub
commit 4fd5fae482
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 153 additions and 14 deletions

View File

@ -69,7 +69,65 @@ public static class OmsRbacRegistrationGuard
return new BusinessException("账号信息已存在,请直接绑定或更换手机号/邮箱");
}
return new BusinessException("注册失败,请稍后重试或联系客服");
if (message.Contains("Data too long", StringComparison.OrdinalIgnoreCase)
|| message.Contains("1406", StringComparison.OrdinalIgnoreCase))
{
if (message.Contains("Avatar", StringComparison.OrdinalIgnoreCase))
{
return new BusinessException("微信头像地址过长,请稍后重试或联系客服");
}
if (message.Contains("Nickname", StringComparison.OrdinalIgnoreCase)
|| message.Contains("CustomerName", StringComparison.OrdinalIgnoreCase)
|| message.Contains("Name", StringComparison.OrdinalIgnoreCase))
{
return new BusinessException("客户名称或微信昵称过长,请修改后重试");
}
return new BusinessException("注册信息字段过长,请缩短客户名称后重试");
}
if (message.Contains("foreign key constraint fails", StringComparison.OrdinalIgnoreCase)
|| message.Contains("1452", StringComparison.OrdinalIgnoreCase))
{
return new BusinessException("客户角色未正确初始化,请联系管理员");
}
if (message.Contains("Cannot insert duplicate key", StringComparison.OrdinalIgnoreCase)
|| message.Contains("2627", StringComparison.OrdinalIgnoreCase))
{
return new BusinessException("账号信息已存在,请直接绑定或更换手机号/邮箱");
}
var reason = ExtractActionableReason(ex);
return new BusinessException($"注册失败:{reason}");
}
private static string ExtractActionableReason(Exception ex)
{
var parts = new List<string>();
for (var current = ex; current != null; current = current.InnerException)
{
if (string.IsNullOrWhiteSpace(current.Message))
{
continue;
}
if (current.Message.Contains("saving the entity changes", StringComparison.OrdinalIgnoreCase))
{
continue;
}
parts.Add(current.Message.Trim());
}
var reason = parts.LastOrDefault();
if (string.IsNullOrWhiteSpace(reason))
{
return "请稍后重试或联系客服";
}
return reason.Length <= 160 ? reason : reason[..160];
}
private static async Task<bool> ExistsActiveUserByAccountAsync(

View File

@ -0,0 +1,31 @@
namespace Oms.Application.Shared;
/// <summary>
/// 微信注册字段裁剪,避免超出库表长度触发保存失败。
/// </summary>
public static class WeChatRegistrationFieldNormalizer
{
public const int CustomerNameMaxLength = 128;
public const int PhoneMaxLength = 16;
public const int EmailMaxLength = 64;
public const int AvatarMaxLength = 255;
public const int NicknameMaxLength = 64;
public const int OpenidMaxLength = 64;
public static string TruncateRequired(string value, int maxLength)
{
var normalized = value.Trim();
return normalized.Length <= maxLength ? normalized : normalized[..maxLength];
}
public static string? TruncateOptional(string? value, int maxLength)
{
var normalized = value?.Trim();
if (string.IsNullOrWhiteSpace(normalized))
{
return null;
}
return normalized.Length <= maxLength ? normalized : normalized[..maxLength];
}
}

View File

@ -15,6 +15,12 @@ public interface ICustomerRepository : IRepository<Customer>
Task<bool> ExistsPhoneAsync(string phone, CancellationToken cancellationToken = default);
Task<bool> ExistsPhoneAnyAsync(string phone, CancellationToken cancellationToken = default);
Task<bool> ExistsEmailAnyAsync(string email, CancellationToken cancellationToken = default);
Task<bool> ExistsWechatOpenidAnyAsync(string wechatOpenid, CancellationToken cancellationToken = default);
/// <summary>
/// 查询指定前缀(WyyMM)下已用顺序号的最大值。
/// </summary>

View File

@ -32,6 +32,33 @@ public class CustomerRepository : OmsSqlSugarRepository<Customer>, ICustomerRepo
return AnyAsync(x => x.Phone == phone, cancellationToken);
}
public async Task<bool> ExistsPhoneAnyAsync(string phone, CancellationToken cancellationToken = default)
{
var db = await GetDbContextAsync(cancellationToken);
var hit = await db.Ado.SqlQuerySingleAsync<int?>(
"SELECT 1 FROM t_customer WHERE Phone = @phone LIMIT 1",
new { phone });
return hit.HasValue;
}
public async Task<bool> ExistsEmailAnyAsync(string email, CancellationToken cancellationToken = default)
{
var db = await GetDbContextAsync(cancellationToken);
var hit = await db.Ado.SqlQuerySingleAsync<int?>(
"SELECT 1 FROM t_customer WHERE Email = @email LIMIT 1",
new { email });
return hit.HasValue;
}
public async Task<bool> ExistsWechatOpenidAnyAsync(string wechatOpenid, CancellationToken cancellationToken = default)
{
var db = await GetDbContextAsync(cancellationToken);
var hit = await db.Ado.SqlQuerySingleAsync<int?>(
"SELECT 1 FROM t_customer WHERE WechatOpenid = @wechatOpenid LIMIT 1",
new { wechatOpenid });
return hit.HasValue;
}
public async Task<int> GetMaxCustomerCodeSequenceForPrefixAsync(
string prefix,
CancellationToken cancellationToken = default)

View File

@ -7,6 +7,7 @@ using Fake.Rbac.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Oms.Application.Shared;
using Oms.Domain.CustomersAggregate.Entities;
using Oms.Domain.CustomersAggregate.Enums;
@ -26,7 +27,8 @@ public class WeChatCustomerService(
ICustomerRepository customerRepository,
UserService userService,
RoleService roleService,
FakeRbacDbContext rbacDbContext) : ApplicationService
FakeRbacDbContext rbacDbContext,
ILogger<WeChatCustomerService> logger) : ApplicationService
{
private const string CustomerRoleCode = "Customer";
@ -80,17 +82,32 @@ public class WeChatCustomerService(
{
ValidateWechatProfile(input.Wechat);
var customerName = NormalizeRequired(input.CustomerName, "客户名称");
var phone = NormalizeRequired(input.Phone, "手机号");
var email = NormalizeRequired(input.Email, "邮箱");
var customerName = WeChatRegistrationFieldNormalizer.TruncateRequired(
NormalizeRequired(input.CustomerName, "客户名称"),
WeChatRegistrationFieldNormalizer.CustomerNameMaxLength);
var phone = WeChatRegistrationFieldNormalizer.TruncateRequired(
NormalizeRequired(input.Phone, "手机号"),
WeChatRegistrationFieldNormalizer.PhoneMaxLength);
var email = WeChatRegistrationFieldNormalizer.TruncateRequired(
NormalizeRequired(input.Email, "邮箱"),
WeChatRegistrationFieldNormalizer.EmailMaxLength);
var password = NormalizeRequired(input.Password, "密码");
var wechatOpenid = WeChatRegistrationFieldNormalizer.TruncateRequired(
input.Wechat.Openid.Trim(),
WeChatRegistrationFieldNormalizer.OpenidMaxLength);
var wechatNickname = WeChatRegistrationFieldNormalizer.TruncateOptional(
input.Wechat.Nickname,
WeChatRegistrationFieldNormalizer.NicknameMaxLength);
var wechatAvatar = WeChatRegistrationFieldNormalizer.TruncateOptional(
input.Wechat.Avatar,
WeChatRegistrationFieldNormalizer.AvatarMaxLength);
if (password.Length < 6)
{
throw new BusinessException("密码长度不能少于6位");
}
if (await customerRepository.GetByWechatOpenidAsync(input.Wechat.Openid, cancellationToken) != null)
if (await customerRepository.ExistsWechatOpenidAnyAsync(wechatOpenid, cancellationToken))
{
throw new BusinessException("当前微信已绑定账号");
}
@ -109,11 +126,10 @@ public class WeChatCustomerService(
Account = phone,
Password = password,
Email = email,
Avatar = NormalizeOptional(input.Wechat.Avatar),
RoleIds = []
Avatar = wechatAvatar,
RoleIds = [customerRoleId]
});
await userService.AssignRolesAsync(user.Id, [customerRoleId]);
var userId = await GetRbacUserMapIdOrThrowAsync(user.Id, cancellationToken);
var entity = new Customer
{
@ -123,9 +139,9 @@ public class WeChatCustomerService(
Phone = phone,
Email = email,
Password = OmsPasswordHelper.ToMd5(password),
WechatOpenid = input.Wechat.Openid,
WechatNickname = NormalizeOptional(input.Wechat.Nickname),
WechatAvatar = NormalizeOptional(input.Wechat.Avatar),
WechatOpenid = wechatOpenid,
WechatNickname = wechatNickname,
WechatAvatar = wechatAvatar,
Status = CustomerStatus.Normal
};
await customerRepository.InsertAsync(entity);
@ -137,6 +153,7 @@ public class WeChatCustomerService(
await TryRollbackRbacUserAsync(user.Id);
}
logger.LogWarning(ex, "微信客户注册失败: phone={Phone}, email={Email}, openid={Openid}", phone, email, wechatOpenid);
throw ex is BusinessException ? ex : OmsRbacRegistrationGuard.ToSaveBusinessException(ex);
}
}
@ -207,12 +224,12 @@ public class WeChatCustomerService(
throw new BusinessException("客户编号已存在");
}
if (await customerRepository.GetByPhoneAsync(phone, cancellationToken) != null)
if (await customerRepository.ExistsPhoneAnyAsync(phone, cancellationToken))
{
throw new BusinessException("手机号已存在");
}
if (await customerRepository.GetByEmailAsync(email, cancellationToken) != null)
if (await customerRepository.ExistsEmailAnyAsync(email, cancellationToken))
{
throw new BusinessException("邮箱已存在");
}