2025-12-25 11:20:56 +08:00
|
|
|
|
namespace Service.EmailParseServices;
|
|
|
|
|
|
|
|
|
|
|
|
public class EmailParseForm95555(
|
|
|
|
|
|
ILogger<EmailParseForm95555> logger,
|
|
|
|
|
|
IOpenAiService openAiService
|
|
|
|
|
|
) : EmailParseServicesBase(logger, openAiService)
|
|
|
|
|
|
{
|
2025-12-25 13:40:26 +08:00
|
|
|
|
public override bool CanParse(string from, string subject, string body)
|
2025-12-25 11:20:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!from.Contains("95555@message.cmbchina.com"))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 13:40:26 +08:00
|
|
|
|
if (!subject.Contains("账户变动通知"))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 11:20:56 +08:00
|
|
|
|
// 不能包含HTML标签
|
|
|
|
|
|
if (Regex.IsMatch(body, "<.*?>"))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override async Task<(
|
|
|
|
|
|
string card,
|
|
|
|
|
|
string reason,
|
|
|
|
|
|
decimal amount,
|
|
|
|
|
|
decimal balance,
|
|
|
|
|
|
TransactionType type,
|
|
|
|
|
|
DateTime? occurredAt
|
|
|
|
|
|
)[]> ParseEmailContentAsync(string emailContent)
|
|
|
|
|
|
{
|
2025-12-31 11:10:10 +08:00
|
|
|
|
var pattern =
|
|
|
|
|
|
"您账户(?<card>\\d+)" +
|
|
|
|
|
|
"于.*?" + // 时间等信息统统吞掉
|
|
|
|
|
|
"(?:(?<type>收入|支出|消费|转入|转出).*?)?" + // 可选 type
|
|
|
|
|
|
"(?:在(?<reason>.*?))?" + // 可选 reason(“财付通-微信支付-这有电快捷支付”)
|
|
|
|
|
|
"(?<amount>\\d+\\.\\d{1,2})元,余额" +
|
|
|
|
|
|
"(?<balance>\\d+\\.\\d{1,2})";
|
2025-12-25 11:20:56 +08:00
|
|
|
|
|
|
|
|
|
|
var matches = Regex.Matches(emailContent, pattern);
|
|
|
|
|
|
|
|
|
|
|
|
if (matches.Count <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogWarning("未能从招商银行邮件内容中解析出交易信息");
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var results = new List<(
|
|
|
|
|
|
string card,
|
|
|
|
|
|
string reason,
|
|
|
|
|
|
decimal amount,
|
|
|
|
|
|
decimal balance,
|
|
|
|
|
|
TransactionType type,
|
|
|
|
|
|
DateTime? occurredAt
|
|
|
|
|
|
)>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Match match in matches)
|
|
|
|
|
|
{
|
|
|
|
|
|
var card = match.Groups["card"].Value;
|
|
|
|
|
|
var reason = match.Groups["reason"].Value;
|
|
|
|
|
|
var amountStr = match.Groups["amount"].Value;
|
|
|
|
|
|
var balanceStr = match.Groups["balance"].Value;
|
|
|
|
|
|
var typeStr = match.Groups["type"].Value;
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(card) &&
|
|
|
|
|
|
!string.IsNullOrEmpty(reason) &&
|
|
|
|
|
|
decimal.TryParse(amountStr, out var amount) &&
|
|
|
|
|
|
decimal.TryParse(balanceStr, out var balance))
|
|
|
|
|
|
{
|
|
|
|
|
|
var type = DetermineTransactionType(typeStr, reason, amount);
|
|
|
|
|
|
results.Add((card, reason, amount, balance, type, null));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return results.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|