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

206 lines
8.0 KiB
Go
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.

package card_apple_order
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/slice"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/os/glog"
"github.com/shopspring/decimal"
"kami/internal/consts"
"kami/internal/errHandler"
"kami/internal/model"
"kami/internal/model/entity"
"kami/internal/service"
"kami/utility/cache"
"kami/utility/config"
"kami/utility/integration/apple"
"kami/utility/pool"
"time"
)
// HandleRedeemResult 处理核销结果,根据不同的状态进行相应的业务操作
func (h *sAppleOrder) handleRedeemResult(ctx context.Context, orderEntity *entity.V1CardAppleRechargeInfo, accountInfo *entity.V1CardAppleAccountInfo) error {
// 调用 Apple 服务进行核销(同步等待)
redeemClient := apple.NewClient()
// 准备推送请求
redeemReq := &apple.RedeemReq{
Account: accountInfo.Account,
Password: accountInfo.Password,
OrderId: orderEntity.OrderNo,
RedemptionCode: orderEntity.CardPass,
}
_, _ = redeemClient.Redeem(ctx, redeemReq)
return nil
}
// handleRedeemSuccess 处理核销成功的情况
func (h *sAppleOrder) handleRedeemSuccess(ctx context.Context, orderEntity *entity.V1CardAppleRechargeInfo, accountInfo *entity.V1CardAppleAccountInfo, balanceBefore, balanceAfter float64) error {
// 将返回的金额字符串转换为 float64假数据处理
actualAmount := orderEntity.CardAmount // 使用卡密面额作为默认金额
// 判断金额是否一致
var orderStatus consts.AppleRechargeOrderStatus
var historyOperation consts.AppleOrderOperation
var remark string
if actualAmount == orderEntity.CardAmount {
orderStatus = consts.AppleRechargeOrderSuccess
historyOperation = consts.AppleRechargeOperationItunesSucceed
} else {
orderStatus = consts.AppleRechargeOrderAmountDifferent
historyOperation = consts.AppleRechargeOperationItunesSucceedButWrongAmount
remark = "金额异议"
}
// 更新订单和账户余额
err := h.UpdateActualAmountAndHistoryAndWallet(ctx, &model.AppleAccountUpdateAmountAndHistoryRecord{
OrderInfo: &model.AppleAccountUpdateAmountRecord{
OrderNo: orderEntity.OrderNo,
Amount: actualAmount,
Status: orderStatus,
Remark: fmt.Sprintf("卡密:%s面额%.2f,实际充值:%.2f,充值账户:%s%s", orderEntity.CardPass, orderEntity.CardAmount, actualAmount, accountInfo.Account, remark),
},
AccountId: accountInfo.Id,
HistoryRemark: remark,
HistoryOperation: historyOperation,
BalanceFromItunes: balanceAfter,
})
if err != nil {
glog.Error(ctx, fmt.Sprintf("更新订单成功记录失败 - 订单号: %s, 错误: %v", orderEntity.OrderNo, err))
return err
}
// 异步回调上游
_ = h.CallBackOrderToUpstream(ctx, orderEntity.OrderNo)
glog.Info(ctx, fmt.Sprintf("订单核销成功处理完毕 - 订单号: %s", orderEntity.OrderNo))
return nil
}
// handleRedeemFailed 处理核销失败的情况
func (h *sAppleOrder) handleRedeemFailed(ctx context.Context, orderEntity *entity.V1CardAppleRechargeInfo, accountInfo *entity.V1CardAppleAccountInfo, errMsg string) error {
// 订单退回待处理状态
err := h.ModifyOrderStatus(ctx, orderEntity.OrderNo, consts.AppleRechargeOrderWaiting, fmt.Sprintf("核销失败:%s", errMsg), nil)
if err != nil {
glog.Error(ctx, fmt.Sprintf("更新订单失败状态失败 - 订单号: %s, 错误: %v", orderEntity.OrderNo, err))
return err
}
// 减少分配计数
_ = h.DecrementDistributionCount(ctx, orderEntity.OrderNo)
// 添加历史记录
_ = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
AccountID: accountInfo.Id,
OrderNo: orderEntity.OrderNo,
RechargeId: int(orderEntity.Id),
AccountName: accountInfo.Account,
Operation: consts.AppleRechargeOperationItunesFail,
Remark: fmt.Sprintf("核销失败:%s", errMsg),
}, nil)
glog.Info(ctx, fmt.Sprintf("订单核销失败,已退回待处理 - 订单号: %s", orderEntity.OrderNo))
return nil
}
// handleAccountInvalid 处理账号失效的情况
func (h *sAppleOrder) handleAccountInvalid(ctx context.Context, orderEntity *entity.V1CardAppleRechargeInfo, accountInfo *entity.V1CardAppleAccountInfo, errMsg string) error {
// 标记当前账号为失效(密码错误或被禁用)
_ = service.AppleAccount().ModifyStatus(ctx, accountInfo.Id, consts.AppleAccountWrongPassword, nil)
// 订单重新设为待调度状态
err := h.ModifyOrderStatus(ctx, orderEntity.OrderNo, consts.AppleRechargeOrderWaiting, "账号失效,待重新分配", nil)
if err != nil {
glog.Error(ctx, fmt.Sprintf("更新订单待处理状态失败 - 订单号: %s, 错误: %v", orderEntity.OrderNo, err))
return err
}
// 减少分配计数,允许重新分配
_ = h.DecrementDistributionCount(ctx, orderEntity.OrderNo)
// 添加历史记录
_ = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
AccountID: accountInfo.Id,
OrderNo: orderEntity.OrderNo,
RechargeId: int(orderEntity.Id),
AccountName: accountInfo.Account,
Operation: consts.AppleRechargeOperationWrongPassword,
Remark: fmt.Sprintf("账号失效:%s", errMsg),
}, nil)
glog.Info(ctx, fmt.Sprintf("账号失效,订单已退回待重新分配 - 订单号: %s, 账号: %s", orderEntity.OrderNo, accountInfo.Account))
return nil
}
// ProcessOrderWithPush 处理订单:根据订单类型判断是立即进行核销处理还是创建定时任务异步处理
// 参数说明:
// - orderEntity: 待处理的订单信息
// - accountInfo: 分配的苹果账号信息
// - immediate: 是否立即处理true: 立即核销false: 异步定时处理)
func (h *sAppleOrder) ProcessOrderWithPush(ctx context.Context) (err error) {
orderEntities, _ := h.GetAccordingOrders(ctx)
if len(orderEntities) == 0 {
return
}
poolClient := pool.New("apple_order_process_push_pool", 1)
for _, orderInfo := range orderEntities {
_ = poolClient.Add(ctx, func(ctx context.Context) {
err = h.processOrderWithAccount(ctx, orderInfo)
if err != nil {
glog.Error(ctx, "处理订单失败", err)
}
})
}
return
}
func (h *sAppleOrder) processOrderWithAccount(ctx context.Context, orderInfo *entity.V1CardAppleRechargeInfo) (err error) {
keys := cache.NewCache().GetPrefixKey(ctx, cache.PrefixAppleAccount)
keysStr := slice.Map(slice.Filter(keys, func(index int, item interface{}) bool {
_, ok := item.(string)
return ok
}), func(index int, item interface{}) string {
return item.(string)
})
accountInfo, err := service.AppleAccount().GetAccordingAccount(ctx, decimal.NewFromFloat(orderInfo.Balance), keysStr)
if err != nil {
glog.Error(ctx, "获取订单账户失败", err)
return
}
cacheVar, err := cache.NewCache().Get(ctx, cache.PrefixAppleAccount.Key(accountInfo.Id))
if err == nil && !cacheVar.IsNil() {
glog.Warning(ctx, "账户正在处理中", accountInfo.Account)
}
_ = cache.NewCache().Set(ctx, cache.PrefixAppleAccount.Key(accountInfo.Id), 1, time.Minute*3)
defer func() {
_, _ = cache.NewCache().Remove(ctx, cache.PrefixAppleAccount.Key(accountInfo.Id))
}()
if err = h.DistributionAccordingAccount(ctx, accountInfo, orderInfo); err != nil {
err = errHandler.WrapError(ctx, gcode.CodeInternalError, err, "分配订单账户失败")
return
}
err = config.GetDatabaseV1().Transaction(ctx, func(ctx2 context.Context, tx gdb.TX) error {
err = service.AppleOrder().ModifyOrderStatus(ctx2, orderInfo.OrderNo, consts.AppleRechargeOrderProcessing, "", tx)
if err != nil {
return err
}
err = service.AppleOrder().AddHistory(ctx2, &model.AppleCardRechargeHistoryInput{
AccountID: accountInfo.Id,
OrderNo: orderInfo.OrderNo,
RechargeId: int(orderInfo.Id),
AccountName: accountInfo.Account,
Operation: consts.AppleRechargeOperationStartRechargeByItunes,
Remark: fmt.Sprintf("分配账户:%s账户余额%.2f", accountInfo.Account, accountInfo.BalanceItunes),
}, tx)
return err
})
if err != nil {
glog.Error(ctx, "修改订单状态失败", err)
}
_ = h.handleRedeemResult(ctx, orderInfo, accountInfo)
return
}