- 实现账号增删改查接口和逻辑 - 支持账号状态更新及状态历史记录功能 - 提供账号列表、历史和统计信息查询API - 实现账号轮询机制,支持按使用时间轮询获取账号 - 增加账号登录流程及批量登录功能,集成接码平台和平台API - 管理账号订单容量,支持容量检查与账号登录触发 - 提供账号池状态统计接口 - 账号历史记录查询支持多种变更类型文本展示 - 密码等敏感信息采用脱敏展示 - 完善日志记录和错误处理机制,保证业务稳定运行
242 lines
7.5 KiB
Go
242 lines
7.5 KiB
Go
package camel_oil
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"kami/internal/consts"
|
||
"kami/internal/dao"
|
||
"kami/internal/model/do"
|
||
"kami/internal/model/entity"
|
||
"kami/utility/config"
|
||
"kami/utility/integration/camel_oil_api"
|
||
"kami/utility/integration/pig"
|
||
|
||
"github.com/gogf/gf/v2/os/glog"
|
||
"github.com/gogf/gf/v2/os/gtime"
|
||
)
|
||
|
||
// CronAccountLoginTask 账号登录任务 - 由cron调度器定期调用
|
||
func (s *sCamelOil) CronAccountLoginTask(ctx context.Context) error {
|
||
|
||
// 检查可用订单容量
|
||
capacity, err := s.GetAvailableOrderCapacity(ctx)
|
||
if err != nil {
|
||
glog.Error(ctx, "获取可用容量失败:", err)
|
||
return err
|
||
}
|
||
|
||
glog.Infof(ctx, "当前可用订单容量: %d", capacity)
|
||
|
||
// 如果容量低于50,继续登录新账号
|
||
if capacity <= 50 {
|
||
err = s.CheckAndTriggerAccountLogin(ctx)
|
||
if err != nil {
|
||
glog.Error(ctx, "触发账号登录失败:", err)
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// CronOrderPaymentCheckTask 订单支付状态检测任务 - 由cron调度器定期调用
|
||
func (s *sCamelOil) CronOrderPaymentCheckTask(ctx context.Context) error {
|
||
glog.Info(ctx, "开始执行订单支付状态检测任务")
|
||
|
||
// 查询待支付订单(创建时间在24小时内)
|
||
var orders []*entity.V1CamelOilOrder
|
||
err := dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilOrder.Columns().PayStatus, consts.CamelOilPaymentStatusUnpaid).
|
||
WhereGTE(dao.V1CamelOilOrder.Columns().CreatedAt, gtime.Now().AddDate(0, 0, -1)).
|
||
Scan(&orders)
|
||
|
||
if err != nil {
|
||
glog.Error(ctx, "查询待支付订单失败:", err)
|
||
return err
|
||
}
|
||
|
||
if len(orders) == 0 {
|
||
glog.Debug(ctx, "无待支付订单")
|
||
return nil
|
||
}
|
||
|
||
glog.Infof(ctx, "查询到 %d 个待支付订单", len(orders))
|
||
|
||
// 检测每个订单的支付状态(使用假数据)
|
||
paidCount := 0
|
||
timeoutCount := 0
|
||
|
||
for _, order := range orders {
|
||
accountInfo, err2 := s.GetAccountInfo(ctx, order.AccountId)
|
||
if err2 != nil {
|
||
glog.Error(ctx, "获取账号信息失败:", err2)
|
||
return err2
|
||
}
|
||
ok, err := camel_oil_api.NewClient().QueryOrder(ctx, accountInfo.Phone, accountInfo.Token, order.PlatformOrderNo)
|
||
if err != nil {
|
||
glog.Error(ctx, "查询订单状态失败:", err)
|
||
}
|
||
if ok {
|
||
// 更新状态
|
||
_, _ = dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilOrder.Columns().Id, order.Id).
|
||
Update(&do.V1CamelOilOrder{
|
||
PaidAt: gtime.Now(),
|
||
PayStatus: int(consts.CamelOilPaymentStatusPaid),
|
||
})
|
||
}
|
||
// 模拟支付状态检测
|
||
// 如果订单创建超过1小时,标记为超时
|
||
if gtime.Now().Sub(order.CreatedAt).Hours() > 1 {
|
||
// 更新为超时
|
||
_, _ = dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilOrder.Columns().Id, order.Id).
|
||
Update(&do.V1CamelOilOrder{
|
||
PayStatus: int(consts.CamelOilPaymentStatusTimeout),
|
||
FailureReason: "支付时间超过一个小时,支付超时",
|
||
})
|
||
_ = s.RecordOrderHistory(ctx, order.OrderNo, "payment_timeout", "", "订单支付超时")
|
||
timeoutCount++
|
||
}
|
||
}
|
||
|
||
glog.Infof(ctx, "订单支付状态检测完成: 已支付=%d, 超时=%d", paidCount, timeoutCount)
|
||
return nil
|
||
}
|
||
|
||
// CronAccountDailyResetTask 账号日重置任务 - 由cron调度器在每日00:05调用
|
||
func (s *sCamelOil) CronAccountDailyResetTask(ctx context.Context) error {
|
||
glog.Info(ctx, "开始执行账号日重置任务")
|
||
|
||
yesterday := gtime.Now().AddDate(0, 0, -1)
|
||
|
||
_, _ = dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilAccount.Columns().Status, consts.CamelOilAccountStatusOnline).
|
||
Update(&do.V1CamelOilAccount{
|
||
DailyOrderCount: 0,
|
||
DailyOrderDate: gtime.Now(),
|
||
})
|
||
|
||
// 查询所有暂停的账号
|
||
var accounts []*entity.V1CamelOilAccount
|
||
err := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilAccount.Columns().Status, consts.CamelOilAccountStatusPaused).
|
||
Scan(&accounts)
|
||
|
||
if err != nil {
|
||
glog.Error(ctx, "查询暂停账号失败:", err)
|
||
return err
|
||
}
|
||
|
||
glog.Infof(ctx, "查询到 %d 个暂停账号", len(accounts))
|
||
|
||
resumedCount := 0
|
||
invalidCount := 0
|
||
|
||
for _, account := range accounts {
|
||
// 检查是否是昨日的记录
|
||
if account.DailyOrderDate == nil || account.DailyOrderDate.Format("Y-m-d") != yesterday.Format("Y-m-d") {
|
||
continue
|
||
}
|
||
|
||
if account.DailyOrderCount >= 10 {
|
||
// 正常完成,重置为在线
|
||
_ = s.UpdateAccountStatus(ctx, account.Id, consts.CamelOilAccountStatusOnline,
|
||
consts.CamelOilAccountChangeTypeResume, "次日重置,恢复使用")
|
||
|
||
// 同时重置日算信息
|
||
_, _ = dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilAccount.Columns().Id, account.Id).
|
||
Update(&do.V1CamelOilAccount{
|
||
DailyOrderCount: 0,
|
||
DailyOrderDate: gtime.Now(),
|
||
})
|
||
|
||
resumedCount++
|
||
} else {
|
||
// 单日下单不足10个,标记为失效
|
||
_ = s.UpdateAccountStatus(ctx, account.Id, consts.CamelOilAccountStatusInvalid,
|
||
consts.CamelOilAccountChangeTypeInvalidate, "单日下单不足10个,账号失效")
|
||
|
||
invalidCount++
|
||
}
|
||
}
|
||
|
||
glog.Infof(ctx, "账号日重置任务完成: 恢复=%d, 失效=%d", resumedCount, invalidCount)
|
||
return nil
|
||
}
|
||
|
||
func (s *sCamelOil) CronVerifyCodeCheckTask(ctx context.Context) error {
|
||
glog.Info(ctx, "开始执行验证码检测任务")
|
||
var accounts []*entity.V1CamelOilAccount
|
||
err := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilAccount.Columns().Status, consts.CamelOilAccountStatusSendCode).
|
||
Scan(&accounts)
|
||
|
||
if err != nil {
|
||
glog.Error(ctx, "查询待验证码账号失败:", err)
|
||
return err
|
||
}
|
||
|
||
glog.Infof(ctx, "查询到 %d 个待验证码账号", len(accounts))
|
||
|
||
successCount := 0
|
||
failCount := 0
|
||
|
||
pigClient := pig.NewClient()
|
||
camelClient := camel_oil_api.NewClient()
|
||
|
||
for _, account := range accounts {
|
||
// 从野猪平台检测验证码是否已接收
|
||
verifyCode, received, err := pigClient.CheckVerifyCode(ctx, account.Phone)
|
||
if err != nil {
|
||
glog.Warningf(ctx, "检测验证码失败,账号ID: %d, 手机号: %s, 错误: %v", account.Id, account.Phone, err)
|
||
failCount++
|
||
continue
|
||
}
|
||
|
||
// 验证码未接收,继续等待
|
||
if !received {
|
||
continue
|
||
}
|
||
|
||
// 验证码已接收,执行登录
|
||
glog.Infof(ctx, "验证码已接收,开始执行登录,账号ID: %d, 手机号: %s", account.Id, account.Phone)
|
||
|
||
// 调用骆驼加油平台执行登录
|
||
token, err := camelClient.LoginWithCaptcha(ctx, account.Phone, verifyCode)
|
||
if err != nil {
|
||
glog.Errorf(ctx, "登录失败,账号ID: %d, 手机号: %s, 错误: %v", account.Id, account.Phone, err)
|
||
// 标记账号失效
|
||
_ = s.UpdateAccountStatus(ctx, account.Id, consts.CamelOilAccountStatusInvalid,
|
||
consts.CamelOilAccountChangeTypeLoginFail, fmt.Sprintf("登录失败: %v", err))
|
||
failCount++
|
||
continue
|
||
}
|
||
|
||
// 保存 token
|
||
_, err = dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1()).
|
||
Where(dao.V1CamelOilAccount.Columns().Id, account.Id).
|
||
Update(&do.V1CamelOilAccount{
|
||
Token: token,
|
||
LastLoginAt: gtime.Now(),
|
||
})
|
||
|
||
if err != nil {
|
||
glog.Errorf(ctx, "保存 token 失败,账号ID: %d, 错误: %v", account.Id, err)
|
||
failCount++
|
||
continue
|
||
}
|
||
|
||
// 调用 UpdateAccountStatus 更新账号状态为在线
|
||
_ = s.UpdateAccountStatus(ctx, account.Id, consts.CamelOilAccountStatusOnline,
|
||
consts.CamelOilAccountChangeTypeLogin, fmt.Sprintf("登录成功,手机号: %s", account.Phone))
|
||
|
||
glog.Infof(ctx, "账号登录成功,ID: %d, 手机号: %s, Token: %s", account.Id, account.Phone, token)
|
||
successCount++
|
||
}
|
||
|
||
glog.Infof(ctx, "验证码检测任务完成: 成功=%d, 失败=%d", successCount, failCount)
|
||
return nil
|
||
}
|