Files
Yi.Framework/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/PayManager.cs
2025-10-12 16:42:26 +08:00

149 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Text.Json;
using Volo.Abp.Domain.Services;
using Volo.Abp.Users;
using Yi.Framework.AiHub.Domain.Entities.Pay;
using Yi.Framework.AiHub.Domain.Shared.Enums;
using Yi.Framework.SqlSugarCore.Abstractions;
using Yi.Framework.AiHub.Domain.Extensions;
namespace Yi.Framework.AiHub.Domain.Managers;
/// <summary>
/// 支付管理器
/// </summary>
public class PayManager : DomainService
{
private readonly ISqlSugarRepository<PayNoticeRecordAggregateRoot, Guid> _payNoticeRepository;
private readonly ICurrentUser _currentUser;
private readonly ISqlSugarRepository<PayOrderAggregateRoot, Guid> _payOrderRepository;
public PayManager(
ISqlSugarRepository<PayNoticeRecordAggregateRoot, Guid> payNoticeRepository,
ICurrentUser currentUser, ISqlSugarRepository<PayOrderAggregateRoot, Guid> payOrderRepository)
{
_payNoticeRepository = payNoticeRepository;
_currentUser = currentUser;
_payOrderRepository = payOrderRepository;
}
/// <summary>
/// 创建订单
/// </summary>
/// <param name="goodsType">商品类型</param>
/// <returns>订单信息</returns>
public async Task<PayOrderAggregateRoot> CreateOrderAsync(GoodsTypeEnum goodsType)
{
// 验证用户是否登录
if (!_currentUser.IsAuthenticated)
{
throw new UserFriendlyException("用户未登录");
}
// 如果是尊享包商品需要验证用户是否为VIP
if (goodsType.IsPremiumPackage())
{
if (!_currentUser.IsAiVip())
{
throw new UserFriendlyException("购买尊享包需要VIP资格请先开通VIP");
}
}
// 生成订单号
var outTradeNo = GenerateOutTradeNo();
// 获取商品信息
var goodsName = goodsType.GetDisplayName();
var totalAmount = goodsType.GetTotalAmount();
// 创建订单实体
var payOrder = new PayOrderAggregateRoot
{
OutTradeNo = outTradeNo,
UserId = _currentUser.GetId(),
UserName = _currentUser.UserName ?? string.Empty,
TotalAmount = totalAmount,
GoodsName = goodsName,
GoodsType = goodsType
};
// 保存订单
await _payOrderRepository.InsertAsync(payOrder);
return payOrder;
}
/// <summary>
/// 更新订单状态
/// </summary>
/// <param name="outTradeNo">商户订单号</param>
/// <param name="tradeStatus">交易状态</param>
/// <param name="tradeNo">支付宝交易号</param>
/// <returns></returns>
public async Task<PayOrderAggregateRoot> UpdateOrderStatusAsync(string outTradeNo, TradeStatusEnum tradeStatus, string? tradeNo = null)
{
var order = await _payOrderRepository.GetFirstAsync(x => x.OutTradeNo == outTradeNo);
if (order == null)
{
throw new UserFriendlyException($"订单不存在:{outTradeNo}");
}
order.TradeStatus = tradeStatus;
if (!string.IsNullOrEmpty(tradeNo))
{
order.TradeNo = tradeNo;
}
await _payOrderRepository.UpdateAsync(order);
return order;
}
/// <summary>
/// 记录支付通知
/// </summary>
/// <param name="notifyData">通知数据</param>
/// <param name="signStr"></param>
/// <returns></returns>
public async Task RecordPayNoticeAsync(Dictionary<string, string> notifyData, string signStr)
{
var payNotice = new PayNoticeRecordAggregateRoot
{
NotifyTime = DateTime.Parse(notifyData.GetValueOrDefault("notify_time", string.Empty)),
TradeNo = notifyData.GetValueOrDefault("trade_no", string.Empty),
OutTradeNo = notifyData.GetValueOrDefault("out_trade_no", string.Empty),
BuyerId = notifyData.GetValueOrDefault("buyer_id", string.Empty),
TradeStatus = ParseTradeStatus(notifyData.GetValueOrDefault("trade_status", string.Empty)),
TotalAmount = decimal.TryParse(notifyData.GetValueOrDefault("total_amount", "-1"), out var amount)
? amount
: 0,
NotifyData = JsonSerializer.Serialize(notifyData),
SignStr = signStr
};
await _payNoticeRepository.InsertAsync(payNotice);
}
/// <summary>
/// 生成商户订单号
/// </summary>
/// <returns></returns>
private string GenerateOutTradeNo()
{
return $"YI_{DateTime.Now:yyyyMMddHHmmss}_{Random.Shared.Next(1000, 9999)}";
}
/// <summary>
/// 解析交易状态
/// </summary>
/// <param name="tradeStatus">状态字符串</param>
/// <returns></returns>
private TradeStatusEnum ParseTradeStatus(string tradeStatus)
{
if (Enum.TryParse<TradeStatusEnum>(tradeStatus, out var result))
{
return result;
}
return TradeStatusEnum.WAIT_TRADE;
}
}