feat(order): enhance order processing logic with improved error handling and user subscription management
This commit is contained in:
parent
8976724c1e
commit
46ab012b6c
File diff suppressed because it is too large
Load Diff
675
queue/logic/order/activateOrderLogic.go_bak
Normal file
675
queue/logic/order/activateOrderLogic.go_bak
Normal file
@ -0,0 +1,675 @@
|
||||
package orderLogic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/config"
|
||||
"github.com/perfect-panel/server/internal/logic/telegram"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/uuidx"
|
||||
"github.com/perfect-panel/server/queue/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
Subscribe = 1
|
||||
Renewal = 2
|
||||
ResetTraffic = 3
|
||||
Recharge = 4
|
||||
)
|
||||
|
||||
type ActivateOrderLogic struct {
|
||||
svc *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewActivateOrderLogic(svc *svc.ServiceContext) *ActivateOrderLogic {
|
||||
return &ActivateOrderLogic{
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ActivateOrderLogic) ProcessTask(ctx context.Context, task *asynq.Task) error {
|
||||
payload := types.ForthwithActivateOrderPayload{}
|
||||
if err := json.Unmarshal(task.Payload(), &payload); err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Unmarshal payload failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("payload", string(task.Payload())),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
// Find order by order no
|
||||
orderInfo, err := l.svc.OrderModel.FindOneByOrderNo(ctx, payload.OrderNo)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find order failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("order_no", payload.OrderNo),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
// 1: Pending, 2: Paid, 3:Close, 4: Failed, 5:Finished
|
||||
if orderInfo.Status != 2 {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Order status error",
|
||||
logger.Field("order_no", orderInfo.OrderNo),
|
||||
logger.Field("status", orderInfo.Status),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
switch orderInfo.Type {
|
||||
case Subscribe:
|
||||
err = l.NewPurchase(ctx, orderInfo)
|
||||
case Renewal:
|
||||
err = l.Renewal(ctx, orderInfo)
|
||||
case ResetTraffic:
|
||||
err = l.ResetTraffic(ctx, orderInfo)
|
||||
case Recharge:
|
||||
err = l.Recharge(ctx, orderInfo)
|
||||
default:
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Order type is invalid", logger.Field("type", orderInfo.Type))
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Process task failed", logger.Field("error", err.Error()))
|
||||
return nil
|
||||
}
|
||||
// if coupon is not empty
|
||||
if orderInfo.Coupon != "" {
|
||||
// update coupon status
|
||||
err = l.svc.CouponModel.UpdateCount(ctx, orderInfo.Coupon)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update coupon status failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("coupon", orderInfo.Coupon),
|
||||
)
|
||||
}
|
||||
}
|
||||
// update order status
|
||||
orderInfo.Status = 5
|
||||
err = l.svc.OrderModel.Update(ctx, orderInfo)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update order status failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("order_no", orderInfo.OrderNo),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPurchase New purchase
|
||||
func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.Order) error {
|
||||
var userInfo *user.User
|
||||
var err error
|
||||
if orderInfo.UserId != 0 {
|
||||
// find user by user id
|
||||
userInfo, err = l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", orderInfo.UserId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// If User ID is 0, it means that the order is a guest order, need to create a new user
|
||||
// query info with redis
|
||||
cacheKey := fmt.Sprintf(constant.TempOrderCacheKey, orderInfo.OrderNo)
|
||||
data, err := l.svc.Redis.Get(ctx, cacheKey).Result()
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Get temp order cache failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("cache_key", cacheKey),
|
||||
)
|
||||
return err
|
||||
}
|
||||
var tempOrder constant.TemporaryOrderInfo
|
||||
if err = json.Unmarshal([]byte(data), &tempOrder); err != nil {
|
||||
logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Unmarshal temp order failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// create user
|
||||
|
||||
userInfo = &user.User{
|
||||
Password: tool.EncodePassWord(tempOrder.Password),
|
||||
AuthMethods: []user.AuthMethods{
|
||||
{
|
||||
AuthType: tempOrder.AuthType,
|
||||
AuthIdentifier: tempOrder.Identifier,
|
||||
},
|
||||
},
|
||||
}
|
||||
err = l.svc.UserModel.Transaction(ctx, func(tx *gorm.DB) error {
|
||||
// Save user information
|
||||
if err := tx.Save(userInfo).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// Generate ReferCode
|
||||
userInfo.ReferCode = uuidx.UserInviteCode(userInfo.Id)
|
||||
// Update ReferCode
|
||||
if err := tx.Model(&user.User{}).Where("id = ?", userInfo.Id).Update("refer_code", userInfo.ReferCode).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
orderInfo.UserId = userInfo.Id
|
||||
return tx.Model(&order.Order{}).Where("order_no = ?", orderInfo.OrderNo).Update("user_id", userInfo.Id).Error
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Create user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
if tempOrder.InviteCode != "" {
|
||||
// find referer by refer code
|
||||
referer, err := l.svc.UserModel.FindOneByReferCode(ctx, tempOrder.InviteCode)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("refer_code", tempOrder.InviteCode),
|
||||
)
|
||||
} else {
|
||||
userInfo.RefererId = referer.Id
|
||||
err = l.svc.UserModel.Update(ctx, userInfo)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user referer failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", userInfo.Id),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).Info("[ActivateOrderLogic] Create guest user success", logger.Field("user_id", userInfo.Id), logger.Field("Identifier", tempOrder.Identifier), logger.Field("AuthType", tempOrder.AuthType))
|
||||
}
|
||||
// find subscribe by id
|
||||
sub, err := l.svc.SubscribeModel.FindOne(ctx, orderInfo.SubscribeId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Find subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("subscribe_id", orderInfo.SubscribeId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// create user subscribe
|
||||
now := time.Now()
|
||||
|
||||
userSub := user.Subscribe{
|
||||
Id: 0,
|
||||
UserId: orderInfo.UserId,
|
||||
OrderId: orderInfo.Id,
|
||||
SubscribeId: orderInfo.SubscribeId,
|
||||
StartTime: now,
|
||||
ExpireTime: tool.AddTime(sub.UnitTime, orderInfo.Quantity, now),
|
||||
Traffic: sub.Traffic,
|
||||
Download: 0,
|
||||
Upload: 0,
|
||||
Token: uuidx.SubscribeToken(orderInfo.OrderNo),
|
||||
UUID: uuid.New().String(),
|
||||
Status: 1,
|
||||
}
|
||||
err = l.svc.UserModel.InsertSubscribe(ctx, &userSub)
|
||||
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert user subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// handler commission
|
||||
if userInfo.RefererId != 0 &&
|
||||
l.svc.Config.Invite.ReferralPercentage != 0 &&
|
||||
(!l.svc.Config.Invite.OnlyFirstPurchase || orderInfo.IsNew) {
|
||||
referer, err := l.svc.UserModel.FindOne(ctx, userInfo.RefererId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("referer_id", userInfo.RefererId),
|
||||
)
|
||||
goto updateCache
|
||||
}
|
||||
// calculate commission
|
||||
amount := float64(orderInfo.Price) * (float64(l.svc.Config.Invite.ReferralPercentage) / 100)
|
||||
referer.Commission += int64(amount)
|
||||
err = l.svc.UserModel.Update(ctx, referer)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update referer commission failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
goto updateCache
|
||||
}
|
||||
// create commission log
|
||||
commissionLog := user.CommissionLog{
|
||||
UserId: referer.Id,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: int64(amount),
|
||||
}
|
||||
err = l.svc.UserModel.InsertCommissionLog(ctx, &commissionLog)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert commission log failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
err = l.svc.UserModel.UpdateUserCache(ctx, referer)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Update referer cache", logger.Field("error", err.Error()), logger.Field("user_id", referer.Id))
|
||||
}
|
||||
}
|
||||
updateCache:
|
||||
for _, id := range tool.StringToInt64Slice(sub.Server) {
|
||||
cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, id)
|
||||
err = l.svc.Redis.Del(ctx, cacheKey).Err()
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Del server user list cache failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("cache_key", cacheKey),
|
||||
)
|
||||
}
|
||||
}
|
||||
data, err := l.svc.ServerModel.FindServerListByGroupIds(ctx, tool.StringToInt64Slice(sub.ServerGroup))
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find server list failed", logger.Field("error", err.Error()))
|
||||
return err
|
||||
}
|
||||
for _, item := range data {
|
||||
cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, item.Id)
|
||||
err = l.svc.Redis.Del(ctx, cacheKey).Err()
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Del server user list cache failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("cache_key", cacheKey),
|
||||
)
|
||||
}
|
||||
}
|
||||
userTelegramChatId, ok := findTelegram(userInfo)
|
||||
|
||||
// sendMessage To Telegram
|
||||
if ok {
|
||||
text, err := tool.RenderTemplateToString(telegram.PurchaseNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"SubscribeName": sub.Name,
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"ExpireTime": userSub.ExpireTime.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendUserNotifyWithTelegram(userTelegramChatId, text)
|
||||
}
|
||||
// send message to admin
|
||||
text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"TradeNo": orderInfo.TradeNo,
|
||||
"SubscribeName": sub.Name,
|
||||
//"UserEmail": userInfo.Email,
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"OrderStatus": "已支付",
|
||||
"OrderTime": orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
"PaymentMethod": orderInfo.Method,
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendAdminNotifyWithTelegram(ctx, text)
|
||||
logger.WithContext(ctx).Info("[ActivateOrderLogic] Insert user subscribe success")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Renewal Renewal
|
||||
func (l *ActivateOrderLogic) Renewal(ctx context.Context, orderInfo *order.Order) error {
|
||||
// find user by user id
|
||||
userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", orderInfo.UserId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// find user subscribe by subscribe token
|
||||
userSub, err := l.svc.UserModel.FindOneSubscribeByToken(ctx, orderInfo.SubscribeToken)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("order_id", orderInfo.Id),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// find subscribe by id
|
||||
sub, err := l.svc.SubscribeModel.FindOne(ctx, orderInfo.SubscribeId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("subscribe_id", orderInfo.SubscribeId),
|
||||
logger.Field("order_id", orderInfo.Id),
|
||||
)
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
if userSub.ExpireTime.Before(now) {
|
||||
userSub.ExpireTime = now
|
||||
}
|
||||
|
||||
// Check whether traffic reset on renewal is enabled
|
||||
if sub.RenewalReset != nil && *sub.RenewalReset {
|
||||
userSub.Download = 0
|
||||
userSub.Upload = 0
|
||||
}
|
||||
if userSub.FinishedAt != nil {
|
||||
userSub.FinishedAt = nil
|
||||
}
|
||||
|
||||
userSub.ExpireTime = tool.AddTime(sub.UnitTime, orderInfo.Quantity, userSub.ExpireTime)
|
||||
userSub.Status = 1
|
||||
// update user subscribe
|
||||
err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// handler commission
|
||||
if userInfo.RefererId != 0 &&
|
||||
l.svc.Config.Invite.ReferralPercentage != 0 &&
|
||||
!l.svc.Config.Invite.OnlyFirstPurchase {
|
||||
referer, err := l.svc.UserModel.FindOne(ctx, userInfo.RefererId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find referer failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("referer_id", userInfo.RefererId),
|
||||
)
|
||||
goto sendMessage
|
||||
}
|
||||
// calculate commission
|
||||
amount := float64(orderInfo.Price) * (float64(l.svc.Config.Invite.ReferralPercentage) / 100)
|
||||
referer.Commission += int64(amount)
|
||||
err = l.svc.UserModel.Update(ctx, referer)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update referer commission failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
goto sendMessage
|
||||
}
|
||||
// create commission log
|
||||
commissionLog := user.CommissionLog{
|
||||
UserId: referer.Id,
|
||||
OrderNo: orderInfo.OrderNo,
|
||||
Amount: int64(amount),
|
||||
}
|
||||
err = l.svc.UserModel.InsertCommissionLog(ctx, &commissionLog)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert commission log failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
err = l.svc.UserModel.UpdateUserCache(ctx, referer)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Errorw("[ActivateOrderLogic] Update referer cache", logger.Field("error", err.Error()), logger.Field("user_id", referer.Id))
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage:
|
||||
userTelegramChatId, ok := findTelegram(userInfo)
|
||||
// SendMessage To Telegram
|
||||
if ok {
|
||||
text, err := tool.RenderTemplateToString(telegram.RenewalNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"SubscribeName": sub.Name,
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"ExpireTime": userSub.ExpireTime.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendUserNotifyWithTelegram(userTelegramChatId, text)
|
||||
}
|
||||
|
||||
// send message to admin
|
||||
text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"TradeNo": orderInfo.TradeNo,
|
||||
"SubscribeName": sub.Name,
|
||||
//"UserEmail": userInfo.Email,
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"OrderStatus": "已支付",
|
||||
"OrderTime": orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
"PaymentMethod": orderInfo.Method,
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendAdminNotifyWithTelegram(ctx, text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetTraffic Reset traffic
|
||||
func (l *ActivateOrderLogic) ResetTraffic(ctx context.Context, orderInfo *order.Order) error {
|
||||
// find user by user id
|
||||
userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", orderInfo.UserId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// Generate a Subscribe Token through orderNo
|
||||
// find user subscribe by subscribe token
|
||||
userSub, err := l.svc.UserModel.FindOneSubscribeByToken(ctx, orderInfo.SubscribeToken)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("order_id", orderInfo.Id),
|
||||
)
|
||||
return err
|
||||
}
|
||||
userSub.Download = 0
|
||||
userSub.Upload = 0
|
||||
userSub.Status = 1
|
||||
// update user subscribe
|
||||
err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
sub, err := l.svc.SubscribeModel.FindOne(ctx, userSub.SubscribeId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find subscribe failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("subscribe_id", userSub.SubscribeId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
userTelegramChatId, ok := findTelegram(userInfo)
|
||||
// SendMessage To Telegram
|
||||
if ok {
|
||||
text, err := tool.RenderTemplateToString(telegram.ResetTrafficNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"SubscribeName": sub.Name,
|
||||
"ResetTime": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"ExpireTime": userSub.ExpireTime.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendUserNotifyWithTelegram(userTelegramChatId, text)
|
||||
}
|
||||
|
||||
// send message to admin
|
||||
text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"TradeNo": orderInfo.TradeNo,
|
||||
"SubscribeName": "流量重置",
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"OrderStatus": "已支付",
|
||||
"OrderTime": orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
"PaymentMethod": orderInfo.Method,
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendAdminNotifyWithTelegram(ctx, text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recharge Recharge to user
|
||||
func (l *ActivateOrderLogic) Recharge(ctx context.Context, orderInfo *order.Order) error {
|
||||
// find user by user id
|
||||
userInfo, err := l.svc.UserModel.FindOne(ctx, orderInfo.UserId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Find user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", orderInfo.UserId),
|
||||
)
|
||||
return err
|
||||
}
|
||||
userInfo.Balance += orderInfo.Price
|
||||
// update user
|
||||
err = l.svc.DB.Transaction(func(tx *gorm.DB) error {
|
||||
err = l.svc.UserModel.Update(ctx, userInfo, tx)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Update user failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// Create Balance Log
|
||||
balanceLog := user.BalanceLog{
|
||||
UserId: orderInfo.UserId,
|
||||
Amount: orderInfo.Price,
|
||||
Type: 1,
|
||||
OrderId: orderInfo.Id,
|
||||
Balance: userInfo.Balance,
|
||||
}
|
||||
err = l.svc.UserModel.InsertBalanceLog(ctx, &balanceLog, tx)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Insert balance log failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Database transaction failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
userTelegramChatId, ok := findTelegram(userInfo)
|
||||
// SendMessage To Telegram
|
||||
if ok {
|
||||
text, err := tool.RenderTemplateToString(telegram.RechargeNotify, map[string]string{
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"PaymentMethod": orderInfo.Method,
|
||||
"Time": orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
"Balance": fmt.Sprintf("%.2f", float64(userInfo.Balance)/100),
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendUserNotifyWithTelegram(userTelegramChatId, text)
|
||||
}
|
||||
// send message to admin
|
||||
text, err := tool.RenderTemplateToString(telegram.AdminOrderNotify, map[string]string{
|
||||
"OrderNo": orderInfo.OrderNo,
|
||||
"TradeNo": orderInfo.TradeNo,
|
||||
"OrderAmount": fmt.Sprintf("%.2f", float64(orderInfo.Price)/100),
|
||||
"SubscribeName": "余额充值",
|
||||
"OrderStatus": "已支付",
|
||||
"OrderTime": orderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
"PaymentMethod": orderInfo.Method,
|
||||
})
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Render AdminOrderNotify template failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
l.sendAdminNotifyWithTelegram(ctx, text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendUserNotifyWithTelegram send message to user
|
||||
func (l *ActivateOrderLogic) sendUserNotifyWithTelegram(chatId int64, text string) {
|
||||
msg := tgbotapi.NewMessage(chatId, text)
|
||||
msg.ParseMode = "markdown"
|
||||
_, err := l.svc.TelegramBot.Send(msg)
|
||||
if err != nil {
|
||||
logger.Error("[ActivateOrderLogic] Send telegram user message failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// sendAdminNotifyWithTelegram send message to admin
|
||||
func (l *ActivateOrderLogic) sendAdminNotifyWithTelegram(ctx context.Context, text string) {
|
||||
admins, err := l.svc.UserModel.QueryAdminUsers(ctx)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Query admin users failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
return
|
||||
}
|
||||
for _, admin := range admins {
|
||||
telegramId, ok := findTelegram(admin)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
msg := tgbotapi.NewMessage(telegramId, text)
|
||||
msg.ParseMode = "markdown"
|
||||
_, err := l.svc.TelegramBot.Send(msg)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("[ActivateOrderLogic] Send telegram admin message failed",
|
||||
logger.Field("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// findTelegram find user telegram id
|
||||
func findTelegram(u *user.User) (int64, bool) {
|
||||
for _, item := range u.AuthMethods {
|
||||
if item.AuthType == "telegram" {
|
||||
// string to int64
|
||||
parseInt, err := strconv.ParseInt(item.AuthIdentifier, 10, 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return parseInt, true
|
||||
}
|
||||
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user