Files
kami_backend/internal/logic/card_apple_order/order.go
danial 15e2426e85 feat(camel_oil): 新增骆驼加油账号管理模块
- 实现账号增删改查接口和逻辑
- 支持账号状态更新及状态历史记录功能
- 提供账号列表、历史和统计信息查询API
- 实现账号轮询机制,支持按使用时间轮询获取账号
- 增加账号登录流程及批量登录功能,集成接码平台和平台API
- 管理账号订单容量,支持容量检查与账号登录触发
- 提供账号池状态统计接口
- 账号历史记录查询支持多种变更类型文本展示
- 密码等敏感信息采用脱敏展示
- 完善日志记录和错误处理机制,保证业务稳定运行
2025-11-21 00:49:50 +08:00

377 lines
14 KiB
Go

package card_apple_order
import (
"context"
"github.com/gogf/gf/v2/os/gmlock"
"kami/api/commonApi"
"kami/internal/consts"
"kami/internal/dao"
"kami/internal/errHandler"
"kami/internal/model"
"kami/internal/model/do"
"kami/internal/model/entity"
"kami/internal/service"
"kami/utility/config"
"kami/utility/utils"
"slices"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// List 获取充值列表
func (h *sAppleOrder) List(ctx context.Context, input model.AppleCardRechargeParamsInput) (total int, data []entity.V1CardAppleRechargeInfo, err error) {
data = make([]entity.V1CardAppleRechargeInfo, 0)
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
if input.StartDate != nil {
m = m.WhereGTE(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, input.StartDate)
}
if input.EndDate != nil {
input.EndDate = input.EndDate.AddDate(0, 0, 1)
m = m.WhereLTE(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, input.EndDate)
}
if input.AccountID != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().AccountId, utils.OrmLike(input.AccountID))
}
if input.OrderNo != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.OrderNo))
}
if input.Attach != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().Attach, utils.OrmLike(input.Attach))
}
if input.CardNo != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.CardNo))
}
if input.CardPass != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().CardPass, utils.OrmLike(input.CardPass))
}
if input.UserId != "" {
m = m.Where(dao.V1CardAppleRechargeInfo.Columns().CreatedUserId, input.UserId)
}
if input.MerchantId != "" {
m = m.Where(dao.V1CardAppleRechargeInfo.Columns().MerchantId, input.MerchantId)
}
if input.Account != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().AccountName, utils.OrmLike(input.Account))
}
err2 := m.Page(input.Current, input.PageSize).
OrderDesc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).
ScanAndCount(&data, &total, false)
if err2 != nil {
total = 0
err = gerror.Wrap(err2, "获取充值订单列表(分页)失败")
}
return
}
// ListWithAccount 获取充值列表(包含账号信息)
func (h *sAppleOrder) ListWithAccount(ctx context.Context, input model.AppleCardRechargeParamsInput) (total int, data []model.AppleCardRechargeListOutput, err error) {
data = make([]model.AppleCardRechargeListOutput, 0)
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
if input.AccountID != "" {
accountEntity, _ := service.AppleAccount().GetDetailById(ctx, input.AccountID)
if accountEntity.Id != "" {
m = m.Where(dao.V1CardAppleRechargeInfo.Columns().AccountId, accountEntity.Account)
}
}
if input.OrderNo != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.OrderNo))
}
if input.Attach != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().Attach, utils.OrmLike(input.Attach))
}
if input.CardNo != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.CardNo))
}
if input.CardPass != "" {
m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().CardPass, utils.OrmLike(input.CardPass))
}
err2 := m.Page(input.Current, input.PageSize).WithAll().
OrderDesc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).
ScanAndCount(&data, &total, true)
if err2 != nil {
total = 0
err = gerror.Wrap(err2, "获取充值订单列表失败")
}
return
}
// AddRechargeOrder 添加一条充值记录
func (h *sAppleOrder) AddRechargeOrder(ctx context.Context, input *model.AppleCardRechargeInput) (orderNo string, err error) {
orderNo = utils.GenerateRandomUUID()
status := consts.AppleRechargeOrderWaiting
operation := consts.AppleRechargeOperationCreated
// 处理二次提交的订单
if targetEntity, _ := h.QueryOneByCardPass(ctx, input.CardPass, nil); targetEntity.Id != 0 &&
targetEntity.Status == int(consts.AppleRechargeOrderAmountDifferent) {
status = consts.AppleRechargeOrderCardNoOrCardPassDuplicated
operation = consts.AppleRechargeOperationDuplicatedOrder
if targetEntity.ActualAmount != input.Amount {
err = gerror.NewCode(errHandler.ErrAppleErrCardPass)
return
}
}
rechargeId, err := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
InsertAndGetId(do.V1CardAppleRechargeInfo{
OrderNo: orderNo,
AccountId: input.AccountID,
AccountName: input.AccountName,
CardNo: input.CardNo,
CardPass: input.CardPass,
Balance: input.Balance,
CardAmount: input.FaceValue,
Status: status,
CallbackUrl: input.CallbackUrl,
Attach: input.Attach,
MerchantId: input.MerchantId,
})
if err != nil {
err = gerror.WrapCode(gcode.CodeDbOperationError, err, "添加充值订单失败")
return "", err
}
err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
RechargeId: int(rechargeId),
OrderNo: orderNo,
AccountName: input.AccountName,
Operation: operation,
}, nil)
if err != nil {
err = gerror.WrapCode(gcode.CodeDbOperationError, err, "添加充值订单历史记录失败")
return "", err
}
return orderNo, err
}
// DistributionAccordingAccount 给指定订单分配一个账户
func (h *sAppleOrder) DistributionAccordingAccount(ctx context.Context, account *entity.V1CardAppleAccountInfo, order *entity.V1CardAppleRechargeInfo) (err error) {
if account == nil || order == nil {
err = gerror.NewCode(gcode.CodeNil)
return
}
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, order.OrderNo)
err = m.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
_, err2 := m.TX(tx).Update(do.V1CardAppleRechargeInfo{
AccountId: account.Id,
AccountName: account.Account,
CreatedUserId: account.CreatedUserId,
})
if err2 != nil {
return err2
}
_, err2 = m.TX(tx).Update(g.Map{
dao.V1CardAppleRechargeInfo.Columns().DistributionCount: gdb.Counter{
Field: dao.V1CardAppleRechargeInfo.Columns().DistributionCount,
Value: 1,
},
})
return err2
})
return err
}
// DecrementDistributionCount 减少分配次数
func (h *sAppleOrder) DecrementDistributionCount(ctx context.Context, orderNo string) (err error) {
_, err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo).
Decrement(dao.V1CardAppleRechargeInfo.Columns().DistributionCount, 1)
return err
}
// UpdateActualAmount 修改订单实际金额
func (h *sAppleOrder) UpdateActualAmount(ctx context.Context, data *model.AppleAccountUpdateAmountRecord, tx gdb.TX) (err error) {
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
if tx != nil {
m = m.TX(tx)
}
_, err = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, data.OrderNo).
Update(do.V1CardAppleRechargeInfo{
ActualAmount: data.Amount,
Status: data.Status,
Remark: data.Remark,
})
return err
}
// UpdateActualAmountAndHistory 添加充值记录
func (h *sAppleOrder) UpdateActualAmountAndHistory(ctx context.Context, record *model.AppleAccountUpdateAmountAndHistoryRecord, tx gdb.TX) (err error) {
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
if tx != nil {
m = m.TX(tx)
}
err = m.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
orderEntity, err2 := h.GetOneByOrderNo(ctx, record.OrderInfo.OrderNo, tx)
if err2 != nil {
return err2
}
if orderEntity.Id == 0 {
return gerror.NewCode(gcode.CodeNil)
}
err2 = h.UpdateActualAmount(ctx, record.OrderInfo, tx)
if err != nil {
return err2
}
err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
RechargeId: int(orderEntity.Id),
OrderNo: orderEntity.OrderNo,
AccountID: orderEntity.AccountId,
AccountName: orderEntity.AccountName,
Operation: record.HistoryOperation,
Remark: record.HistoryRemark,
}, tx)
return err
})
return
}
func (h *sAppleOrder) UpdateActualAmountAndHistoryAndWallet(ctx context.Context, m *model.AppleAccountUpdateAmountAndHistoryRecord) (err error) {
err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
if err = h.UpdateActualAmountAndHistory(ctx, m, tx); err != nil {
return err
}
//往钱包里充值
_, err = service.AppleAccount().AddWalletAmount(ctx, &model.AppleCardWalletInfo{
CommonStrId: commonApi.CommonStrId{ID: m.AccountId},
OrderNo: m.OrderInfo.OrderNo,
Amount: m.OrderInfo.Amount,
BalanceFromItunes: m.BalanceFromItunes,
Remark: m.WalletRemark,
}, tx)
return err
})
//if err != nil {
// newPool := pool.New(pool.AppleAccountCheckWallet, 10)
// _ = newPool.Add(ctx, func(ctx context.Context) {
// orderEntity, err2 := h.GetOneByOrderNo(ctx, m.OrderInfo.OrderNo, nil)
// if err2 != nil {
// return
// }
// //检查余额是否正常
// service.AppleAccount().CheckWalletHistoryNormal(ctx, orderEntity.AccountId)
// })
//}
return
}
// GetListByStatus 获取指定状态的订单
func (h *sAppleOrder) GetListByStatus(ctx context.Context, statusList []consts.AppleRechargeOrderStatus) (data entity.V1CardAppleRechargeInfo, err error) {
// 切片
err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
WhereIn(dao.V1CardAppleRechargeInfo.Columns().Status, statusList).
Scan(&data)
return
}
// GetTodayRechargeAmountByAccountID 获取当前账户今日的充值金额
func (h *sAppleOrder) GetTodayRechargeAmountByAccountID(ctx context.Context, accountID string) (amount float64, err error) {
amount, err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleRechargeInfo.Columns().AccountId, accountID).
Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderProcessing).
Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderSuccess).
Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderAmountDifferent).
WhereBetween(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, gtime.Now().StartOfDay(), gtime.Now()).
Sum(dao.V1CardAppleRechargeInfo.Columns().ActualAmount)
return
}
// GetRechargeStatusByOrderNo 通过订单号查询当前订单充值状态
func (h *sAppleOrder) GetRechargeStatusByOrderNo(ctx context.Context, orderNo string) (status int, err error) {
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
err = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo).Scan(&status)
return
}
// GetOneByOrderNo 通过订单号查询当前订单充值
func (h *sAppleOrder) GetOneByOrderNo(ctx context.Context, orderNo string, tx gdb.TX, id ...int64) (data entity.V1CardAppleRechargeInfo, err error) {
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
if tx != nil {
m = m.TX(tx)
}
if orderNo != "" {
m = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo)
}
if len(id) != 0 && id[0] != 0 {
m = m.Where(dao.V1CardAppleRechargeInfo.Columns().Id, id[0])
}
err = m.Scan(&data)
return
}
func (h *sAppleOrder) GetOneByMerchantId(ctx context.Context, merchantId string) (data *entity.V1CardAppleRechargeInfo, err error) {
err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleRechargeInfo.Columns().MerchantId, merchantId).
Scan(&data)
return
}
// GetAccordingOrder 找到符合条件的订单
// 最早提交等待处理的订单
func (h *sAppleOrder) GetAccordingOrder(ctx context.Context) (data *entity.V1CardAppleRechargeInfo, err error) {
gmlock.Lock("sAppleOrder_GetAccordingOrder")
defer gmlock.Unlock("sAppleOrder_GetAccordingOrder")
m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderWaiting).
OrderAsc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt)
total, err := m.Count()
for i := 0; i < total; i++ {
// 这一行可以没必要
data = &entity.V1CardAppleRechargeInfo{}
err = m.Scan(data)
err = utils.HandleNoRowsError(err)
if data.Id == 0 || data.DistributionCount < consts.AppleOrderMaxDistributionCount {
break
}
err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = h.ModifyOrderStatus(ctx, data.OrderNo, consts.AppleRechargeOrderFreeze, "订单回调超过最大次数", tx)
if err != nil {
return err
}
err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
RechargeId: int(data.Id),
OrderNo: data.OrderNo,
AccountID: data.AccountId,
AccountName: data.AccountName,
Operation: consts.AppleRechargeOperationCallBackTimeout,
Remark: "itunes调用订单超过最大次数",
}, tx)
return err
})
data = &entity.V1CardAppleRechargeInfo{}
}
return
}
// GetAccordingOrders 找到符合条件的订单
func (h *sAppleOrder) GetAccordingOrders(ctx context.Context) (list []*entity.V1CardAppleRechargeInfo, err error) {
gmlock.Lock("sAppleOrder_GetAccordingOrders")
defer gmlock.Unlock("sAppleOrder_GetAccordingOrders")
_ = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderWaiting).
OrderAsc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).Scan(&list)
slices.DeleteFunc(list, func(v *entity.V1CardAppleRechargeInfo) bool {
if v.Id == 0 || v.DistributionCount < consts.AppleOrderMaxDistributionCount {
return false
}
err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
err = h.ModifyOrderStatus(ctx, v.OrderNo, consts.AppleRechargeOrderFreeze, "订单回调超过最大次数", tx)
if err != nil {
return err
}
err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
RechargeId: int(v.Id),
OrderNo: v.OrderNo,
AccountID: v.AccountId,
AccountName: v.AccountName,
Operation: consts.AppleRechargeOperationCallBackTimeout,
Remark: "itunes调用订单超过最大次数",
}, tx)
return err
})
return true
})
return
}